Make dptr_path() and dptr_wcard() const.
[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         SMB_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
2300         if (total_params < 13) {
2301                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2302                 goto out;
2303         }
2304
2305         dirtype = SVAL(params,0);
2306         maxentries = SVAL(params,2);
2307         findfirst_flags = SVAL(params,4);
2308         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2309         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2310         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2311         info_level = SVAL(params,6);
2312
2313         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2314 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2315                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2316                 info_level, max_data_bytes));
2317
2318         if (!maxentries) {
2319                 /* W2K3 seems to treat zero as 1. */
2320                 maxentries = 1;
2321         }
2322
2323         switch (info_level) {
2324                 case SMB_FIND_INFO_STANDARD:
2325                 case SMB_FIND_EA_SIZE:
2326                 case SMB_FIND_EA_LIST:
2327                 case SMB_FIND_FILE_DIRECTORY_INFO:
2328                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2329                 case SMB_FIND_FILE_NAMES_INFO:
2330                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2331                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2332                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2333                         break;
2334                 case SMB_FIND_FILE_UNIX:
2335                 case SMB_FIND_FILE_UNIX_INFO2:
2336                         /* Always use filesystem for UNIX mtime query. */
2337                         ask_sharemode = false;
2338                         if (!lp_unix_extensions()) {
2339                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2340                                 goto out;
2341                         }
2342                         ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2343                         break;
2344                 default:
2345                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2346                         goto out;
2347         }
2348
2349         srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2350                               params+12, total_params - 12,
2351                               STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2352         if (!NT_STATUS_IS_OK(ntstatus)) {
2353                 reply_nterror(req, ntstatus);
2354                 goto out;
2355         }
2356
2357         ntstatus = filename_convert(ctx, conn,
2358                                     req->flags2 & FLAGS2_DFS_PATHNAMES,
2359                                     directory,
2360                                     ucf_flags,
2361                                     &mask_contains_wcard,
2362                                     &smb_dname);
2363         if (!NT_STATUS_IS_OK(ntstatus)) {
2364                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2365                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2366                                         ERRSRV, ERRbadpath);
2367                         goto out;
2368                 }
2369                 reply_nterror(req, ntstatus);
2370                 goto out;
2371         }
2372
2373         mask = smb_dname->original_lcomp;
2374
2375         directory = smb_dname->base_name;
2376
2377         p = strrchr_m(directory,'/');
2378         if(p == NULL) {
2379                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2380                 if((directory[0] == '.') && (directory[1] == '\0')) {
2381                         mask = talloc_strdup(ctx,"*");
2382                         if (!mask) {
2383                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2384                                 goto out;
2385                         }
2386                         mask_contains_wcard = True;
2387                 }
2388         } else {
2389                 *p = 0;
2390         }
2391
2392         if (p == NULL || p == directory) {
2393                 /* Ensure we don't have a directory name of "". */
2394                 directory = talloc_strdup(talloc_tos(), ".");
2395                 if (!directory) {
2396                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2397                         goto out;
2398                 }
2399         }
2400
2401         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2402
2403         if (info_level == SMB_FIND_EA_LIST) {
2404                 uint32 ea_size;
2405
2406                 if (total_data < 4) {
2407                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2408                         goto out;
2409                 }
2410
2411                 ea_size = IVAL(pdata,0);
2412                 if (ea_size != total_data) {
2413                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2414 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2415                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2416                         goto out;
2417                 }
2418
2419                 if (!lp_ea_support(SNUM(conn))) {
2420                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2421                         goto out;
2422                 }
2423
2424                 /* Pull out the list of names. */
2425                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2426                 if (!ea_list) {
2427                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2428                         goto out;
2429                 }
2430         }
2431
2432         *ppdata = (char *)SMB_REALLOC(
2433                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2434         if(*ppdata == NULL ) {
2435                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2436                 goto out;
2437         }
2438         pdata = *ppdata;
2439         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2440
2441         /* Realloc the params space */
2442         *pparams = (char *)SMB_REALLOC(*pparams, 10);
2443         if (*pparams == NULL) {
2444                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2445                 goto out;
2446         }
2447         params = *pparams;
2448
2449         /* Save the wildcard match and attribs we are using on this directory -
2450                 needed as lanman2 assumes these are being saved between calls */
2451
2452         ntstatus = dptr_create(conn,
2453                                 NULL, /* fsp */
2454                                 directory,
2455                                 False,
2456                                 True,
2457                                 req->smbpid,
2458                                 mask,
2459                                 mask_contains_wcard,
2460                                 dirtype,
2461                                 &dirptr);
2462
2463         if (!NT_STATUS_IS_OK(ntstatus)) {
2464                 reply_nterror(req, ntstatus);
2465                 goto out;
2466         }
2467
2468         dptr_num = dptr_dnum(dirptr);
2469         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2470
2471         /* Initialize per TRANS2_FIND_FIRST operation data */
2472         dptr_init_search_op(dirptr);
2473
2474         /* We don't need to check for VOL here as this is returned by
2475                 a different TRANS2 call. */
2476
2477         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2478                 directory,lp_dontdescend(SNUM(conn))));
2479         if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2480                 dont_descend = True;
2481
2482         p = pdata;
2483         space_remaining = max_data_bytes;
2484         out_of_space = False;
2485
2486         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2487                 bool got_exact_match = False;
2488
2489                 /* this is a heuristic to avoid seeking the dirptr except when
2490                         absolutely necessary. It allows for a filename of about 40 chars */
2491                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2492                         out_of_space = True;
2493                         finished = False;
2494                 } else {
2495                         finished = !get_lanman2_dir_entry(ctx,
2496                                         conn,
2497                                         dirptr,
2498                                         req->flags2,
2499                                         mask,dirtype,info_level,
2500                                         requires_resume_key,dont_descend,
2501                                         ask_sharemode,
2502                                         &p,pdata,data_end,
2503                                         space_remaining, &out_of_space,
2504                                         &got_exact_match,
2505                                         &last_entry_off, ea_list);
2506                 }
2507
2508                 if (finished && out_of_space)
2509                         finished = False;
2510
2511                 if (!finished && !out_of_space)
2512                         numentries++;
2513
2514                 /*
2515                  * As an optimisation if we know we aren't looking
2516                  * for a wildcard name (ie. the name matches the wildcard exactly)
2517                  * then we can finish on any (first) match.
2518                  * This speeds up large directory searches. JRA.
2519                  */
2520
2521                 if(got_exact_match)
2522                         finished = True;
2523
2524                 /* Ensure space_remaining never goes -ve. */
2525                 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2526                         space_remaining = 0;
2527                         out_of_space = true;
2528                 } else {
2529                         space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2530                 }
2531         }
2532
2533         /* Check if we can close the dirptr */
2534         if(close_after_first || (finished && close_if_end)) {
2535                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2536                 dptr_close(sconn, &dptr_num);
2537         }
2538
2539         /*
2540          * If there are no matching entries we must return ERRDOS/ERRbadfile -
2541          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2542          * the protocol level is less than NT1. Tested with smbclient. JRA.
2543          * This should fix the OS/2 client bug #2335.
2544          */
2545
2546         if(numentries == 0) {
2547                 dptr_close(sconn, &dptr_num);
2548                 if (get_Protocol() < PROTOCOL_NT1) {
2549                         reply_force_doserror(req, ERRDOS, ERRnofiles);
2550                         goto out;
2551                 } else {
2552                         reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2553                                         ERRDOS, ERRbadfile);
2554                         goto out;
2555                 }
2556         }
2557
2558         /* At this point pdata points to numentries directory entries. */
2559
2560         /* Set up the return parameter block */
2561         SSVAL(params,0,dptr_num);
2562         SSVAL(params,2,numentries);
2563         SSVAL(params,4,finished);
2564         SSVAL(params,6,0); /* Never an EA error */
2565         SSVAL(params,8,last_entry_off);
2566
2567         send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2568                             max_data_bytes);
2569
2570         if ((! *directory) && dptr_path(sconn, dptr_num)) {
2571                 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2572                 if (!directory) {
2573                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2574                 }
2575         }
2576
2577         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2578                 smb_fn_name(req->cmd),
2579                 mask, directory, dirtype, numentries ) );
2580
2581         /*
2582          * Force a name mangle here to ensure that the
2583          * mask as an 8.3 name is top of the mangled cache.
2584          * The reasons for this are subtle. Don't remove
2585          * this code unless you know what you are doing
2586          * (see PR#13758). JRA.
2587          */
2588
2589         if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2590                 char mangled_name[13];
2591                 name_to_8_3(mask, mangled_name, True, conn->params);
2592         }
2593  out:
2594         TALLOC_FREE(smb_dname);
2595         return;
2596 }
2597
2598 /****************************************************************************
2599  Reply to a TRANS2_FINDNEXT.
2600 ****************************************************************************/
2601
2602 static void call_trans2findnext(connection_struct *conn,
2603                                 struct smb_request *req,
2604                                 char **pparams, int total_params,
2605                                 char **ppdata, int total_data,
2606                                 unsigned int max_data_bytes)
2607 {
2608         /* We must be careful here that we don't return more than the
2609                 allowed number of data bytes. If this means returning fewer than
2610                 maxentries then so be it. We assume that the redirector has
2611                 enough room for the fixed number of parameter bytes it has
2612                 requested. */
2613         char *params = *pparams;
2614         char *pdata = *ppdata;
2615         char *data_end;
2616         int dptr_num;
2617         int maxentries;
2618         uint16 info_level;
2619         uint32 resume_key;
2620         uint16 findnext_flags;
2621         bool close_after_request;
2622         bool close_if_end;
2623         bool requires_resume_key;
2624         bool continue_bit;
2625         bool mask_contains_wcard = False;
2626         char *resume_name = NULL;
2627         const char *mask = NULL;
2628         const char *directory = NULL;
2629         char *p = NULL;
2630         uint16 dirtype;
2631         int numentries = 0;
2632         int i, last_entry_off=0;
2633         bool finished = False;
2634         bool dont_descend = False;
2635         bool out_of_space = False;
2636         int space_remaining;
2637         struct ea_list *ea_list = NULL;
2638         NTSTATUS ntstatus = NT_STATUS_OK;
2639         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2640         TALLOC_CTX *ctx = talloc_tos();
2641         struct dptr_struct *dirptr;
2642         struct smbd_server_connection *sconn = req->sconn;
2643
2644         if (total_params < 13) {
2645                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2646                 return;
2647         }
2648
2649         dptr_num = SVAL(params,0);
2650         maxentries = SVAL(params,2);
2651         info_level = SVAL(params,4);
2652         resume_key = IVAL(params,6);
2653         findnext_flags = SVAL(params,10);
2654         close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2655         close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2656         requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2657         continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2658
2659         if (!continue_bit) {
2660                 /* We only need resume_name if continue_bit is zero. */
2661                 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2662                               params+12,
2663                               total_params - 12, STR_TERMINATE, &ntstatus,
2664                               &mask_contains_wcard);
2665                 if (!NT_STATUS_IS_OK(ntstatus)) {
2666                         /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2667                            complain (it thinks we're asking for the directory above the shared
2668                            path or an invalid name). Catch this as the resume name is only compared, never used in
2669                            a file access. JRA. */
2670                         srvstr_pull_talloc(ctx, params, req->flags2,
2671                                 &resume_name, params+12,
2672                                 total_params - 12,
2673                                 STR_TERMINATE);
2674
2675                         if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2676                                 reply_nterror(req, ntstatus);
2677                                 return;
2678                         }
2679                 }
2680         }
2681
2682         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2683 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2684 resume_key = %d resume name = %s continue=%d level = %d\n",
2685                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
2686                 requires_resume_key, resume_key,
2687                 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2688
2689         if (!maxentries) {
2690                 /* W2K3 seems to treat zero as 1. */
2691                 maxentries = 1;
2692         }
2693
2694         switch (info_level) {
2695                 case SMB_FIND_INFO_STANDARD:
2696                 case SMB_FIND_EA_SIZE:
2697                 case SMB_FIND_EA_LIST:
2698                 case SMB_FIND_FILE_DIRECTORY_INFO:
2699                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2700                 case SMB_FIND_FILE_NAMES_INFO:
2701                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2702                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2703                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2704                         break;
2705                 case SMB_FIND_FILE_UNIX:
2706                 case SMB_FIND_FILE_UNIX_INFO2:
2707                         /* Always use filesystem for UNIX mtime query. */
2708                         ask_sharemode = false;
2709                         if (!lp_unix_extensions()) {
2710                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2711                                 return;
2712                         }
2713                         break;
2714                 default:
2715                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2716                         return;
2717         }
2718
2719         if (info_level == SMB_FIND_EA_LIST) {
2720                 uint32 ea_size;
2721
2722                 if (total_data < 4) {
2723                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2724                         return;
2725                 }
2726
2727                 ea_size = IVAL(pdata,0);
2728                 if (ea_size != total_data) {
2729                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2730 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2731                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2732                         return;
2733                 }
2734
2735                 if (!lp_ea_support(SNUM(conn))) {
2736                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2737                         return;
2738                 }
2739
2740                 /* Pull out the list of names. */
2741                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2742                 if (!ea_list) {
2743                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2744                         return;
2745                 }
2746         }
2747
2748         *ppdata = (char *)SMB_REALLOC(
2749                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2750         if(*ppdata == NULL) {
2751                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2752                 return;
2753         }
2754
2755         pdata = *ppdata;
2756         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2757
2758         /* Realloc the params space */
2759         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2760         if(*pparams == NULL ) {
2761                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2762                 return;
2763         }
2764
2765         params = *pparams;
2766
2767         /* Check that the dptr is valid */
2768         if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2769                 reply_nterror(req, STATUS_NO_MORE_FILES);
2770                 return;
2771         }
2772
2773         directory = dptr_path(sconn, dptr_num);
2774
2775         /* Get the wildcard mask from the dptr */
2776         if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2777                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2778                 reply_nterror(req, STATUS_NO_MORE_FILES);
2779                 return;
2780         }
2781
2782         /* Get the attr mask from the dptr */
2783         dirtype = dptr_attr(sconn, dptr_num);
2784
2785         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2786                 dptr_num, mask, dirtype,
2787                 (long)dirptr,
2788                 dptr_TellDir(dirptr)));
2789
2790         /* Initialize per TRANS2_FIND_NEXT operation data */
2791         dptr_init_search_op(dirptr);
2792
2793         /* We don't need to check for VOL here as this is returned by
2794                 a different TRANS2 call. */
2795
2796         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2797                  directory,lp_dontdescend(SNUM(conn))));
2798         if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2799                 dont_descend = True;
2800
2801         p = pdata;
2802         space_remaining = max_data_bytes;
2803         out_of_space = False;
2804
2805         /*
2806          * Seek to the correct position. We no longer use the resume key but
2807          * depend on the last file name instead.
2808          */
2809
2810         if(!continue_bit && resume_name && *resume_name) {
2811                 SMB_STRUCT_STAT st;
2812
2813                 long current_pos = 0;
2814                 /*
2815                  * Remember, name_to_8_3 is called by
2816                  * get_lanman2_dir_entry(), so the resume name
2817                  * could be mangled. Ensure we check the unmangled name.
2818                  */
2819
2820                 if (mangle_is_mangled(resume_name, conn->params)) {
2821                         char *new_resume_name = NULL;
2822                         mangle_lookup_name_from_8_3(ctx,
2823                                                 resume_name,
2824                                                 &new_resume_name,
2825                                                 conn->params);
2826                         if (new_resume_name) {
2827                                 resume_name = new_resume_name;
2828                         }
2829                 }
2830
2831                 /*
2832                  * Fix for NT redirector problem triggered by resume key indexes
2833                  * changing between directory scans. We now return a resume key of 0
2834                  * and instead look for the filename to continue from (also given
2835                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2836                  * findfirst/findnext (as is usual) then the directory pointer
2837                  * should already be at the correct place.
2838                  */
2839
2840                 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2841         } /* end if resume_name && !continue_bit */
2842
2843         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2844                 bool got_exact_match = False;
2845
2846                 /* this is a heuristic to avoid seeking the dirptr except when 
2847                         absolutely necessary. It allows for a filename of about 40 chars */
2848                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2849                         out_of_space = True;
2850                         finished = False;
2851                 } else {
2852                         finished = !get_lanman2_dir_entry(ctx,
2853                                                 conn,
2854                                                 dirptr,
2855                                                 req->flags2,
2856                                                 mask,dirtype,info_level,
2857                                                 requires_resume_key,dont_descend,
2858                                                 ask_sharemode,
2859                                                 &p,pdata,data_end,
2860                                                 space_remaining, &out_of_space,
2861                                                 &got_exact_match,
2862                                                 &last_entry_off, ea_list);
2863                 }
2864
2865                 if (finished && out_of_space)
2866                         finished = False;
2867
2868                 if (!finished && !out_of_space)
2869                         numentries++;
2870
2871                 /*
2872                  * As an optimisation if we know we aren't looking
2873                  * for a wildcard name (ie. the name matches the wildcard exactly)
2874                  * then we can finish on any (first) match.
2875                  * This speeds up large directory searches. JRA.
2876                  */
2877
2878                 if(got_exact_match)
2879                         finished = True;
2880
2881                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2882         }
2883
2884         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2885                 smb_fn_name(req->cmd),
2886                 mask, directory, dirtype, numentries ) );
2887
2888         /* Check if we can close the dirptr */
2889         if(close_after_request || (finished && close_if_end)) {
2890                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2891                 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2892         }
2893
2894         /* Set up the return parameter block */
2895         SSVAL(params,0,numentries);
2896         SSVAL(params,2,finished);
2897         SSVAL(params,4,0); /* Never an EA error */
2898         SSVAL(params,6,last_entry_off);
2899
2900         send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2901                             max_data_bytes);
2902
2903         return;
2904 }
2905
2906 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2907 {
2908         E_md4hash(lp_servicename(SNUM(conn)),objid);
2909         return objid;
2910 }
2911
2912 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2913 {
2914         SMB_ASSERT(extended_info != NULL);
2915
2916         extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2917         extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2918                                        | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2919                                        | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2920 #ifdef SAMBA_VERSION_REVISION
2921         extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2922 #endif
2923         extended_info->samba_subversion = 0;
2924 #ifdef SAMBA_VERSION_RC_RELEASE
2925         extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2926 #else
2927 #ifdef SAMBA_VERSION_PRE_RELEASE
2928         extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2929 #endif
2930 #endif
2931 #ifdef SAMBA_VERSION_VENDOR_PATCH
2932         extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2933 #endif
2934         extended_info->samba_gitcommitdate = 0;
2935 #ifdef SAMBA_VERSION_COMMIT_TIME
2936         unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2937 #endif
2938
2939         memset(extended_info->samba_version_string, 0,
2940                sizeof(extended_info->samba_version_string));
2941
2942         snprintf (extended_info->samba_version_string,
2943                   sizeof(extended_info->samba_version_string),
2944                   "%s", samba_version_string());
2945 }
2946
2947 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2948                          TALLOC_CTX *mem_ctx,
2949                          uint16_t info_level,
2950                          uint16_t flags2,
2951                          unsigned int max_data_bytes,
2952                          char **ppdata,
2953                          int *ret_data_len)
2954 {
2955         char *pdata, *end_data;
2956         int data_len = 0, len;
2957         const char *vname = volume_label(SNUM(conn));
2958         int snum = SNUM(conn);
2959         char *fstype = lp_fstype(SNUM(conn));
2960         uint32 additional_flags = 0;
2961         struct smb_filename smb_fname_dot;
2962         SMB_STRUCT_STAT st;
2963
2964         if (IS_IPC(conn)) {
2965                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2966                         DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2967                                 "info level (0x%x) on IPC$.\n",
2968                                 (unsigned int)info_level));
2969                         return NT_STATUS_ACCESS_DENIED;
2970                 }
2971         }
2972
2973         DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2974
2975         ZERO_STRUCT(smb_fname_dot);
2976         smb_fname_dot.base_name = discard_const_p(char, ".");
2977
2978         if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2979                 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2980                 return map_nt_error_from_unix(errno);
2981         }
2982
2983         st = smb_fname_dot.st;
2984
2985         *ppdata = (char *)SMB_REALLOC(
2986                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2987         if (*ppdata == NULL) {
2988                 return NT_STATUS_NO_MEMORY;
2989         }
2990
2991         pdata = *ppdata;
2992         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2993         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2994
2995         switch (info_level) {
2996                 case SMB_INFO_ALLOCATION:
2997                 {
2998                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2999                         data_len = 18;
3000                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3001                                 return map_nt_error_from_unix(errno);
3002                         }
3003
3004                         block_size = lp_block_size(snum);
3005                         if (bsize < block_size) {
3006                                 uint64_t factor = block_size/bsize;
3007                                 bsize = block_size;
3008                                 dsize /= factor;
3009                                 dfree /= factor;
3010                         }
3011                         if (bsize > block_size) {
3012                                 uint64_t factor = bsize/block_size;
3013                                 bsize = block_size;
3014                                 dsize *= factor;
3015                                 dfree *= factor;
3016                         }
3017                         bytes_per_sector = 512;
3018                         sectors_per_unit = bsize/bytes_per_sector;
3019
3020                         DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3021 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3022                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3023
3024                         SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3025                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3026                         SIVAL(pdata,l1_cUnit,dsize);
3027                         SIVAL(pdata,l1_cUnitAvail,dfree);
3028                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
3029                         break;
3030                 }
3031
3032                 case SMB_INFO_VOLUME:
3033                         /* Return volume name */
3034                         /* 
3035                          * Add volume serial number - hash of a combination of
3036                          * the called hostname and the service name.
3037                          */
3038                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3039                         /*
3040                          * Win2k3 and previous mess this up by sending a name length
3041                          * one byte short. I believe only older clients (OS/2 Win9x) use
3042                          * this call so try fixing this by adding a terminating null to
3043                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3044                          */
3045                         len = srvstr_push(
3046                                 pdata, flags2,
3047                                 pdata+l2_vol_szVolLabel, vname,
3048                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3049                                 STR_NOALIGN|STR_TERMINATE);
3050                         SCVAL(pdata,l2_vol_cch,len);
3051                         data_len = l2_vol_szVolLabel + len;
3052                         DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3053                                  (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3054                                  len, vname));
3055                         break;
3056
3057                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3058                 case SMB_FS_ATTRIBUTE_INFORMATION:
3059
3060                         additional_flags = 0;
3061 #if defined(HAVE_SYS_QUOTAS)
3062                         additional_flags |= FILE_VOLUME_QUOTAS;
3063 #endif
3064
3065                         if(lp_nt_acl_support(SNUM(conn))) {
3066                                 additional_flags |= FILE_PERSISTENT_ACLS;
3067                         }
3068
3069                         /* Capabilities are filled in at connection time through STATVFS call */
3070                         additional_flags |= conn->fs_capabilities;
3071                         additional_flags |= lp_parm_int(conn->params->service,
3072                                                         "share", "fake_fscaps",
3073                                                         0);
3074
3075                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3076                                 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3077                                 additional_flags); /* FS ATTRIBUTES */
3078
3079                         SIVAL(pdata,4,255); /* Max filename component length */
3080                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3081                                 and will think we can't do long filenames */
3082                         len = srvstr_push(pdata, flags2, pdata+12, fstype,
3083                                           PTR_DIFF(end_data, pdata+12),
3084                                           STR_UNICODE);
3085                         SIVAL(pdata,8,len);
3086                         data_len = 12 + len;
3087                         break;
3088
3089                 case SMB_QUERY_FS_LABEL_INFO:
3090                 case SMB_FS_LABEL_INFORMATION:
3091                         len = srvstr_push(pdata, flags2, pdata+4, vname,
3092                                           PTR_DIFF(end_data, pdata+4), 0);
3093                         data_len = 4 + len;
3094                         SIVAL(pdata,0,len);
3095                         break;
3096
3097                 case SMB_QUERY_FS_VOLUME_INFO:      
3098                 case SMB_FS_VOLUME_INFORMATION:
3099
3100                         /* 
3101                          * Add volume serial number - hash of a combination of
3102                          * the called hostname and the service name.
3103                          */
3104                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
3105                                 (str_checksum(get_local_machine_name())<<16));
3106
3107                         /* Max label len is 32 characters. */
3108                         len = srvstr_push(pdata, flags2, pdata+18, vname,
3109                                           PTR_DIFF(end_data, pdata+18),
3110                                           STR_UNICODE);
3111                         SIVAL(pdata,12,len);
3112                         data_len = 18+len;
3113
3114                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3115                                 (int)strlen(vname),vname, lp_servicename(snum)));
3116                         break;
3117
3118                 case SMB_QUERY_FS_SIZE_INFO:
3119                 case SMB_FS_SIZE_INFORMATION:
3120                 {
3121                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3122                         data_len = 24;
3123                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3124                                 return map_nt_error_from_unix(errno);
3125                         }
3126                         block_size = lp_block_size(snum);
3127                         if (bsize < block_size) {
3128                                 uint64_t factor = block_size/bsize;
3129                                 bsize = block_size;
3130                                 dsize /= factor;
3131                                 dfree /= factor;
3132                         }
3133                         if (bsize > block_size) {
3134                                 uint64_t factor = bsize/block_size;
3135                                 bsize = block_size;
3136                                 dsize *= factor;
3137                                 dfree *= factor;
3138                         }
3139                         bytes_per_sector = 512;
3140                         sectors_per_unit = bsize/bytes_per_sector;
3141                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3142 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3143                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3144                         SBIG_UINT(pdata,0,dsize);
3145                         SBIG_UINT(pdata,8,dfree);
3146                         SIVAL(pdata,16,sectors_per_unit);
3147                         SIVAL(pdata,20,bytes_per_sector);
3148                         break;
3149                 }
3150
3151                 case SMB_FS_FULL_SIZE_INFORMATION:
3152                 {
3153                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3154                         data_len = 32;
3155                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3156                                 return map_nt_error_from_unix(errno);
3157                         }
3158                         block_size = lp_block_size(snum);
3159                         if (bsize < block_size) {
3160                                 uint64_t factor = block_size/bsize;
3161                                 bsize = block_size;
3162                                 dsize /= factor;
3163                                 dfree /= factor;
3164                         }
3165                         if (bsize > block_size) {
3166                                 uint64_t factor = bsize/block_size;
3167                                 bsize = block_size;
3168                                 dsize *= factor;
3169                                 dfree *= factor;
3170                         }
3171                         bytes_per_sector = 512;
3172                         sectors_per_unit = bsize/bytes_per_sector;
3173                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3174 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3175                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3176                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3177                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3178                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3179                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3180                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3181                         break;
3182                 }
3183
3184                 case SMB_QUERY_FS_DEVICE_INFO:
3185                 case SMB_FS_DEVICE_INFORMATION:
3186                 {
3187                         uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3188
3189                         if (!CAN_WRITE(conn)) {
3190                                 characteristics |= FILE_READ_ONLY_DEVICE;
3191                         }
3192                         data_len = 8;
3193                         SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3194                         SIVAL(pdata,4,characteristics);
3195                         break;
3196                 }
3197
3198 #ifdef HAVE_SYS_QUOTAS
3199                 case SMB_FS_QUOTA_INFORMATION:
3200                 /* 
3201                  * what we have to send --metze:
3202                  *
3203                  * Unknown1:            24 NULL bytes
3204                  * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3205                  * Hard Quota Limit:    8 bytes seems like uint64_t or so
3206                  * Quota Flags:         2 byte :
3207                  * Unknown3:            6 NULL bytes
3208                  *
3209                  * 48 bytes total
3210                  * 
3211                  * details for Quota Flags:
3212                  * 
3213                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3214                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
3215                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3216                  * 0x0001 Enable Quotas: enable quota for this fs
3217                  *
3218                  */
3219                 {
3220                         /* we need to fake up a fsp here,
3221                          * because its not send in this call
3222                          */
3223                         files_struct fsp;
3224                         SMB_NTQUOTA_STRUCT quotas;
3225
3226                         ZERO_STRUCT(fsp);
3227                         ZERO_STRUCT(quotas);
3228
3229                         fsp.conn = conn;
3230                         fsp.fnum = -1;
3231
3232                         /* access check */
3233                         if (get_current_uid(conn) != 0) {
3234                                 DEBUG(0,("set_user_quota: access_denied "
3235                                          "service [%s] user [%s]\n",
3236                                          lp_servicename(SNUM(conn)),
3237                                          conn->session_info->unix_info->unix_name));
3238                                 return NT_STATUS_ACCESS_DENIED;
3239                         }
3240
3241                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3242                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3243                                 return map_nt_error_from_unix(errno);
3244                         }
3245
3246                         data_len = 48;
3247
3248                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3249                                   lp_servicename(SNUM(conn))));
3250
3251                         /* Unknown1 24 NULL bytes*/
3252                         SBIG_UINT(pdata,0,(uint64_t)0);
3253                         SBIG_UINT(pdata,8,(uint64_t)0);
3254                         SBIG_UINT(pdata,16,(uint64_t)0);
3255
3256                         /* Default Soft Quota 8 bytes */
3257                         SBIG_UINT(pdata,24,quotas.softlim);
3258
3259                         /* Default Hard Quota 8 bytes */
3260                         SBIG_UINT(pdata,32,quotas.hardlim);
3261
3262                         /* Quota flag 2 bytes */
3263                         SSVAL(pdata,40,quotas.qflags);
3264
3265                         /* Unknown3 6 NULL bytes */
3266                         SSVAL(pdata,42,0);
3267                         SIVAL(pdata,44,0);
3268
3269                         break;
3270                 }
3271 #endif /* HAVE_SYS_QUOTAS */
3272                 case SMB_FS_OBJECTID_INFORMATION:
3273                 {
3274                         unsigned char objid[16];
3275                         struct smb_extended_info extended_info;
3276                         memcpy(pdata,create_volume_objectid(conn, objid),16);
3277                         samba_extended_info_version (&extended_info);
3278                         SIVAL(pdata,16,extended_info.samba_magic);
3279                         SIVAL(pdata,20,extended_info.samba_version);
3280                         SIVAL(pdata,24,extended_info.samba_subversion);
3281                         SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3282                         memcpy(pdata+36,extended_info.samba_version_string,28);
3283                         data_len = 64;
3284                         break;
3285                 }
3286
3287                 /*
3288                  * Query the version and capabilities of the CIFS UNIX extensions
3289                  * in use.
3290                  */
3291
3292                 case SMB_QUERY_CIFS_UNIX_INFO:
3293                 {
3294                         bool large_write = lp_min_receive_file_size() &&
3295                                         !srv_is_signing_active(conn->sconn);
3296                         bool large_read = !srv_is_signing_active(conn->sconn);
3297                         int encrypt_caps = 0;
3298
3299                         if (!lp_unix_extensions()) {
3300                                 return NT_STATUS_INVALID_LEVEL;
3301                         }
3302
3303                         switch (conn->encrypt_level) {
3304                         case 0:
3305                                 encrypt_caps = 0;
3306                                 break;
3307                         case 1:
3308                         case Auto:
3309                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3310                                 break;
3311                         case Required:
3312                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3313                                                 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3314                                 large_write = false;
3315                                 large_read = false;
3316                                 break;
3317                         }
3318
3319                         data_len = 12;
3320                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3321                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3322
3323                         /* We have POSIX ACLs, pathname, encryption, 
3324                          * large read/write, and locking capability. */
3325
3326                         SBIG_UINT(pdata,4,((uint64_t)(
3327                                         CIFS_UNIX_POSIX_ACLS_CAP|
3328                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
3329                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
3330                                         CIFS_UNIX_EXTATTR_CAP|
3331                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3332                                         encrypt_caps|
3333                                         (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3334                                         (large_write ?
3335                                         CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3336                         break;
3337                 }
3338
3339                 case SMB_QUERY_POSIX_FS_INFO:
3340                 {
3341                         int rc;
3342                         vfs_statvfs_struct svfs;
3343
3344                         if (!lp_unix_extensions()) {
3345                                 return NT_STATUS_INVALID_LEVEL;
3346                         }
3347
3348                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3349
3350                         if (!rc) {
3351                                 data_len = 56;
3352                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
3353                                 SIVAL(pdata,4,svfs.BlockSize);
3354                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3355                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3356                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3357                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3358                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3359                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3360                                 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3361 #ifdef EOPNOTSUPP
3362                         } else if (rc == EOPNOTSUPP) {
3363                                 return NT_STATUS_INVALID_LEVEL;
3364 #endif /* EOPNOTSUPP */
3365                         } else {
3366                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3367                                 return NT_STATUS_DOS(ERRSRV, ERRerror);
3368                         }
3369                         break;
3370                 }
3371
3372                 case SMB_QUERY_POSIX_WHOAMI:
3373                 {
3374                         uint32_t flags = 0;
3375                         uint32_t sid_bytes;
3376                         int i;
3377
3378                         if (!lp_unix_extensions()) {
3379                                 return NT_STATUS_INVALID_LEVEL;
3380                         }
3381
3382                         if (max_data_bytes < 40) {
3383                                 return NT_STATUS_BUFFER_TOO_SMALL;
3384                         }
3385
3386                         /* We ARE guest if global_sid_Builtin_Guests is
3387                          * in our list of SIDs.
3388                          */
3389                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
3390                                                conn->session_info->security_token)) {
3391                                 flags |= SMB_WHOAMI_GUEST;
3392                         }
3393
3394                         /* We are NOT guest if global_sid_Authenticated_Users
3395                          * is in our list of SIDs.
3396                          */
3397                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
3398                                                conn->session_info->security_token)) {
3399                                 flags &= ~SMB_WHOAMI_GUEST;
3400                         }
3401
3402                         /* NOTE: 8 bytes for UID/GID, irrespective of native
3403                          * platform size. This matches
3404                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
3405                          */
3406                         data_len = 4 /* flags */
3407                             + 4 /* flag mask */
3408                             + 8 /* uid */
3409                             + 8 /* gid */
3410                             + 4 /* ngroups */
3411                             + 4 /* num_sids */
3412                             + 4 /* SID bytes */
3413                             + 4 /* pad/reserved */
3414                             + (conn->session_info->unix_token->ngroups * 8)
3415                                 /* groups list */
3416                             + (conn->session_info->security_token->num_sids *
3417                                     SID_MAX_SIZE)
3418                                 /* SID list */;
3419
3420                         SIVAL(pdata, 0, flags);
3421                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3422                         SBIG_UINT(pdata, 8,
3423                                   (uint64_t)conn->session_info->unix_token->uid);
3424                         SBIG_UINT(pdata, 16,
3425                                   (uint64_t)conn->session_info->unix_token->gid);
3426
3427
3428                         if (data_len >= max_data_bytes) {
3429                                 /* Potential overflow, skip the GIDs and SIDs. */
3430
3431                                 SIVAL(pdata, 24, 0); /* num_groups */
3432                                 SIVAL(pdata, 28, 0); /* num_sids */
3433                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3434                                 SIVAL(pdata, 36, 0); /* reserved */
3435
3436                                 data_len = 40;
3437                                 break;
3438                         }
3439
3440                         SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3441                         SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3442
3443                         /* We walk the SID list twice, but this call is fairly
3444                          * infrequent, and I don't expect that it's performance
3445                          * sensitive -- jpeach
3446                          */
3447                         for (i = 0, sid_bytes = 0;
3448                              i < conn->session_info->security_token->num_sids; ++i) {
3449                                 sid_bytes += ndr_size_dom_sid(
3450                                         &conn->session_info->security_token->sids[i],
3451                                         0);
3452                         }
3453
3454                         /* SID list byte count */
3455                         SIVAL(pdata, 32, sid_bytes);
3456
3457                         /* 4 bytes pad/reserved - must be zero */
3458                         SIVAL(pdata, 36, 0);
3459                         data_len = 40;
3460
3461                         /* GID list */
3462                         for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3463                                 SBIG_UINT(pdata, data_len,
3464                                           (uint64_t)conn->session_info->unix_token->groups[i]);
3465                                 data_len += 8;
3466                         }
3467
3468                         /* SID list */
3469                         for (i = 0;
3470                             i < conn->session_info->security_token->num_sids; ++i) {
3471                                 int sid_len = ndr_size_dom_sid(
3472                                         &conn->session_info->security_token->sids[i],
3473                                         0);
3474
3475                                 sid_linearize(pdata + data_len, sid_len,
3476                                     &conn->session_info->security_token->sids[i]);
3477                                 data_len += sid_len;
3478                         }
3479
3480                         break;
3481                 }
3482
3483                 case SMB_MAC_QUERY_FS_INFO:
3484                         /*
3485                          * Thursby MAC extension... ONLY on NTFS filesystems
3486                          * once we do streams then we don't need this
3487                          */
3488                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3489                                 data_len = 88;
3490                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
3491                                 break;
3492                         }
3493                         /* drop through */
3494                 default:
3495                         return NT_STATUS_INVALID_LEVEL;
3496         }
3497
3498         *ret_data_len = data_len;
3499         return NT_STATUS_OK;
3500 }
3501
3502 /****************************************************************************
3503  Reply to a TRANS2_QFSINFO (query filesystem info).
3504 ****************************************************************************/
3505
3506 static void call_trans2qfsinfo(connection_struct *conn,
3507                                struct smb_request *req,
3508                                char **pparams, int total_params,
3509                                char **ppdata, int total_data,
3510                                unsigned int max_data_bytes)
3511 {
3512         char *params = *pparams;
3513         uint16_t info_level;
3514         int data_len = 0;
3515         NTSTATUS status;
3516
3517         if (total_params < 2) {
3518                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3519                 return;
3520         }
3521
3522         info_level = SVAL(params,0);
3523
3524         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3525                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3526                         DEBUG(0,("call_trans2qfsinfo: encryption required "
3527                                 "and info level 0x%x sent.\n",
3528                                 (unsigned int)info_level));
3529                         exit_server_cleanly("encryption required "
3530                                 "on connection");
3531                         return;
3532                 }
3533         }
3534
3535         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3536
3537         status = smbd_do_qfsinfo(conn, req,
3538                                  info_level,
3539                                  req->flags2,
3540                                  max_data_bytes,
3541                                  ppdata, &data_len);
3542         if (!NT_STATUS_IS_OK(status)) {
3543                 reply_nterror(req, status);
3544                 return;
3545         }
3546
3547         send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3548                             max_data_bytes);
3549
3550         DEBUG( 4, ( "%s info_level = %d\n",
3551                     smb_fn_name(req->cmd), info_level) );
3552
3553         return;
3554 }
3555
3556 /****************************************************************************
3557  Reply to a TRANS2_SETFSINFO (set filesystem info).
3558 ****************************************************************************/
3559
3560 static void call_trans2setfsinfo(connection_struct *conn,
3561                                  struct smb_request *req,
3562                                  char **pparams, int total_params,
3563                                  char **ppdata, int total_data,
3564                                  unsigned int max_data_bytes)
3565 {
3566         struct smbd_server_connection *sconn = req->sconn;
3567         char *pdata = *ppdata;
3568         char *params = *pparams;
3569         uint16 info_level;
3570
3571         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3572
3573         /*  */
3574         if (total_params < 4) {
3575                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3576                         total_params));
3577                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3578                 return;
3579         }
3580
3581         info_level = SVAL(params,2);
3582
3583         if (IS_IPC(conn)) {
3584                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3585                                 info_level != SMB_SET_CIFS_UNIX_INFO) {
3586                         DEBUG(0,("call_trans2setfsinfo: not an allowed "
3587                                 "info level (0x%x) on IPC$.\n",
3588                                 (unsigned int)info_level));
3589                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3590                         return;
3591                 }
3592         }
3593
3594         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3595                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3596                         DEBUG(0,("call_trans2setfsinfo: encryption required "
3597                                 "and info level 0x%x sent.\n",
3598                                 (unsigned int)info_level));
3599                         exit_server_cleanly("encryption required "
3600                                 "on connection");
3601                         return;
3602                 }
3603         }
3604
3605         switch(info_level) {
3606                 case SMB_SET_CIFS_UNIX_INFO:
3607                         if (!lp_unix_extensions()) {
3608                                 reply_nterror(req,
3609                                               NT_STATUS_INVALID_LEVEL);
3610                                 return;
3611                         }
3612
3613                         /* There should be 12 bytes of capabilities set. */
3614                         if (total_data < 8) {
3615                                 reply_nterror(
3616                                         req,
3617                                         NT_STATUS_INVALID_PARAMETER);
3618                                 return;
3619                         }
3620                         sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3621                         sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3622                         sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3623                         sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3624                         /* Just print these values for now. */
3625                         DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3626                                    "major = %u, minor = %u cap_low = 0x%x, "
3627                                    "cap_high = 0x%xn",
3628                                    (unsigned int)sconn->
3629                                    smb1.unix_info.client_major,
3630                                    (unsigned int)sconn->
3631                                    smb1.unix_info.client_minor,
3632                                    (unsigned int)sconn->
3633                                    smb1.unix_info.client_cap_low,
3634                                    (unsigned int)sconn->
3635                                    smb1.unix_info.client_cap_high));
3636
3637                         /* Here is where we must switch to posix pathname processing... */
3638                         if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3639                                 lp_set_posix_pathnames();
3640                                 mangle_change_to_posix();
3641                         }
3642
3643                         if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3644                             !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3645                                 /* Client that knows how to do posix locks,
3646                                  * but not posix open/mkdir operations. Set a
3647                                  * default type for read/write checks. */
3648
3649                                 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3650
3651                         }
3652                         break;
3653
3654                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3655                         {
3656                                 NTSTATUS status;
3657                                 size_t param_len = 0;
3658                                 size_t data_len = total_data;
3659
3660                                 if (!lp_unix_extensions()) {
3661                                         reply_nterror(
3662                                                 req,
3663                                                 NT_STATUS_INVALID_LEVEL);
3664                                         return;
3665                                 }
3666
3667                                 if (lp_smb_encrypt(SNUM(conn)) == false) {
3668                                         reply_nterror(
3669                                                 req,
3670                                                 NT_STATUS_NOT_SUPPORTED);
3671                                         return;
3672                                 }
3673
3674                                 if (req->sconn->smb1.echo_handler.trusted_fde) {
3675                                         DEBUG( 2,("call_trans2setfsinfo: "
3676                                                 "request transport encryption disabled"
3677                                                 "with 'fork echo handler = yes'\n"));
3678                                         reply_nterror(
3679                                                 req,
3680                                                 NT_STATUS_NOT_SUPPORTED);
3681                                         return;
3682                                 }
3683
3684                                 DEBUG( 4,("call_trans2setfsinfo: "
3685                                         "request transport encryption.\n"));
3686
3687                                 status = srv_request_encryption_setup(conn,
3688                                                                 (unsigned char **)ppdata,
3689                                                                 &data_len,
3690                                                                 (unsigned char **)pparams,
3691                                                                 &param_len);
3692
3693                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3694                                                 !NT_STATUS_IS_OK(status)) {
3695                                         reply_nterror(req, status);
3696                                         return;
3697                                 }
3698
3699                                 send_trans2_replies(conn, req,
3700                                                 *pparams,
3701                                                 param_len,
3702                                                 *ppdata,
3703                                                 data_len,
3704                                                 max_data_bytes);
3705
3706                                 if (NT_STATUS_IS_OK(status)) {
3707                                         /* Server-side transport
3708                                          * encryption is now *on*. */
3709                                         status = srv_encryption_start(conn);
3710                                         if (!NT_STATUS_IS_OK(status)) {
3711                                                 char *reason = talloc_asprintf(talloc_tos(),
3712                                                                                "Failure in setting "
3713                                                                                "up encrypted transport: %s",
3714                                                                                nt_errstr(status));
3715                                                 exit_server_cleanly(reason);
3716                                         }
3717                                 }
3718                                 return;
3719                         }
3720
3721                 case SMB_FS_QUOTA_INFORMATION:
3722                         {
3723                                 files_struct *fsp = NULL;
3724                                 SMB_NTQUOTA_STRUCT quotas;
3725
3726                                 ZERO_STRUCT(quotas);
3727
3728                                 /* access check */
3729                                 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3730                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3731                                                  lp_servicename(SNUM(conn)),
3732                                                  conn->session_info->unix_info->unix_name));
3733                                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3734                                         return;
3735                                 }
3736
3737                                 /* note: normaly there're 48 bytes,
3738                                  * but we didn't use the last 6 bytes for now 
3739                                  * --metze 
3740                                  */
3741                                 fsp = file_fsp(req, SVAL(params,0));
3742
3743                                 if (!check_fsp_ntquota_handle(conn, req,
3744                                                               fsp)) {
3745                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3746                                         reply_nterror(
3747                                                 req, NT_STATUS_INVALID_HANDLE);
3748                                         return;
3749                                 }
3750
3751                                 if (total_data < 42) {
3752                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3753                                                 total_data));
3754                                         reply_nterror(
3755                                                 req,
3756                                                 NT_STATUS_INVALID_PARAMETER);
3757                                         return;
3758                                 }
3759
3760                                 /* unknown_1 24 NULL bytes in pdata*/
3761
3762                                 /* the soft quotas 8 bytes (uint64_t)*/
3763                                 quotas.softlim = BVAL(pdata,24);
3764
3765                                 /* the hard quotas 8 bytes (uint64_t)*/
3766                                 quotas.hardlim = BVAL(pdata,32);
3767
3768                                 /* quota_flags 2 bytes **/
3769                                 quotas.qflags = SVAL(pdata,40);
3770
3771                                 /* unknown_2 6 NULL bytes follow*/
3772
3773                                 /* now set the quotas */
3774                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3775                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3776                                         reply_nterror(req, map_nt_error_from_unix(errno));
3777                                         return;
3778                                 }
3779
3780                                 break;
3781                         }
3782                 default:
3783                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3784                                 info_level));
3785                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3786                         return;
3787                         break;
3788         }
3789
3790         /* 
3791          * sending this reply works fine, 
3792          * but I'm not sure it's the same 
3793          * like windows do...
3794          * --metze
3795          */
3796         reply_outbuf(req, 10, 0);
3797 }
3798
3799 #if defined(HAVE_POSIX_ACLS)
3800 /****************************************************************************
3801  Utility function to count the number of entries in a POSIX acl.
3802 ****************************************************************************/
3803
3804 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3805 {
3806         unsigned int ace_count = 0;
3807         int entry_id = SMB_ACL_FIRST_ENTRY;
3808         SMB_ACL_ENTRY_T entry;
3809
3810         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3811                 /* get_next... */
3812                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3813                         entry_id = SMB_ACL_NEXT_ENTRY;
3814                 }
3815                 ace_count++;
3816         }
3817         return ace_count;
3818 }
3819
3820 /****************************************************************************
3821  Utility function to marshall a POSIX acl into wire format.
3822 ****************************************************************************/
3823
3824 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3825 {
3826         int entry_id = SMB_ACL_FIRST_ENTRY;
3827         SMB_ACL_ENTRY_T entry;
3828
3829         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3830                 SMB_ACL_TAG_T tagtype;
3831                 SMB_ACL_PERMSET_T permset;
3832                 unsigned char perms = 0;
3833                 unsigned int own_grp;
3834
3835                 /* get_next... */
3836                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3837                         entry_id = SMB_ACL_NEXT_ENTRY;
3838                 }
3839
3840                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3841                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3842                         return False;
3843                 }
3844
3845                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3846                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3847                         return False;
3848                 }
3849
3850                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3851                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3852                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3853
3854                 SCVAL(pdata,1,perms);
3855
3856                 switch (tagtype) {
3857                         case SMB_ACL_USER_OBJ:
3858                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3859                                 own_grp = (unsigned int)pst->st_ex_uid;
3860                                 SIVAL(pdata,2,own_grp);
3861                                 SIVAL(pdata,6,0);
3862                                 break;
3863                         case SMB_ACL_USER:
3864                                 {
3865                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3866                                         if (!puid) {
3867                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3868                                                 return False;
3869                                         }
3870                                         own_grp = (unsigned int)*puid;
3871                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3872                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3873                                         SIVAL(pdata,2,own_grp);
3874                                         SIVAL(pdata,6,0);
3875                                         break;
3876                                 }
3877                         case SMB_ACL_GROUP_OBJ:
3878                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3879                                 own_grp = (unsigned int)pst->st_ex_gid;
3880                                 SIVAL(pdata,2,own_grp);
3881                                 SIVAL(pdata,6,0);
3882                                 break;
3883                         case SMB_ACL_GROUP:
3884                                 {
3885                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3886                                         if (!pgid) {
3887                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3888                                                 return False;
3889                                         }
3890                                         own_grp = (unsigned int)*pgid;
3891                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3892                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3893                                         SIVAL(pdata,2,own_grp);
3894                                         SIVAL(pdata,6,0);
3895                                         break;
3896                                 }
3897                         case SMB_ACL_MASK:
3898                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3899                                 SIVAL(pdata,2,0xFFFFFFFF);
3900                                 SIVAL(pdata,6,0xFFFFFFFF);
3901                                 break;
3902                         case SMB_ACL_OTHER:
3903                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3904                                 SIVAL(pdata,2,0xFFFFFFFF);
3905                                 SIVAL(pdata,6,0xFFFFFFFF);
3906                                 break;
3907                         default:
3908                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3909                                 return False;
3910                 }
3911                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3912         }
3913
3914         return True;
3915 }
3916 #endif
3917
3918 /****************************************************************************
3919  Store the FILE_UNIX_BASIC info.
3920 ****************************************************************************/
3921
3922 static char *store_file_unix_basic(connection_struct *conn,
3923                                 char *pdata,
3924                                 files_struct *fsp,
3925                                 const SMB_STRUCT_STAT *psbuf)
3926 {
3927         uint64_t file_index = get_FileIndex(conn, psbuf);
3928
3929         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3930         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3931
3932         SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
3933         pdata += 8;
3934
3935         SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3936         pdata += 8;
3937
3938         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime);       /* Change Time 64 Bit */
3939         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime);     /* Last access time 64 Bit */
3940         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
3941         pdata += 24;
3942
3943         SIVAL(pdata,0,psbuf->st_ex_uid);               /* user id for the owner */
3944         SIVAL(pdata,4,0);
3945         pdata += 8;
3946
3947         SIVAL(pdata,0,psbuf->st_ex_gid);               /* group id of owner */
3948         SIVAL(pdata,4,0);
3949         pdata += 8;
3950
3951         SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3952         pdata += 4;
3953
3954         SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev));   /* Major device number if type is device */
3955         SIVAL(pdata,4,0);
3956         pdata += 8;
3957
3958         SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev));   /* Minor device number if type is device */
3959         SIVAL(pdata,4,0);
3960         pdata += 8;
3961
3962         SINO_T_VAL(pdata,0,(SMB_INO_T)file_index);   /* inode number */
3963         pdata += 8;
3964
3965         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode));     /* Standard UNIX file permissions */
3966         SIVAL(pdata,4,0);
3967         pdata += 8;
3968
3969         SIVAL(pdata,0,psbuf->st_ex_nlink);             /* number of hard links */
3970         SIVAL(pdata,4,0);
3971         pdata += 8;
3972
3973         return pdata;
3974 }
3975
3976 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3977  * the chflags(2) (or equivalent) flags.
3978  *
3979  * XXX: this really should be behind the VFS interface. To do this, we would
3980  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3981  * Each VFS module could then implement its own mapping as appropriate for the
3982  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3983  */
3984 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3985         info2_flags_map[] =
3986 {
3987 #ifdef UF_NODUMP
3988     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3989 #endif
3990
3991 #ifdef UF_IMMUTABLE
3992     { UF_IMMUTABLE, EXT_IMMUTABLE },
3993 #endif
3994
3995 #ifdef UF_APPEND
3996     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3997 #endif
3998
3999 #ifdef UF_HIDDEN
4000     { UF_HIDDEN, EXT_HIDDEN },
4001 #endif
4002
4003     /* Do not remove. We need to guarantee that this array has at least one
4004      * entry to build on HP-UX.
4005      */
4006     { 0, 0 }
4007
4008 };
4009
4010 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4011                                 uint32 *smb_fflags, uint32 *smb_fmask)
4012 {
4013         int i;
4014
4015         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4016             *smb_fmask |= info2_flags_map[i].smb_fflag;
4017             if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4018                     *smb_fflags |= info2_flags_map[i].smb_fflag;
4019             }
4020         }
4021 }
4022
4023 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4024                                 const uint32 smb_fflags,
4025                                 const uint32 smb_fmask,
4026                                 int *stat_fflags)
4027 {
4028         uint32 max_fmask = 0;
4029         int i;
4030
4031         *stat_fflags = psbuf->st_ex_flags;
4032
4033         /* For each flags requested in smb_fmask, check the state of the
4034          * corresponding flag in smb_fflags and set or clear the matching
4035          * stat flag.
4036          */
4037
4038         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4039             max_fmask |= info2_flags_map[i].smb_fflag;
4040             if (smb_fmask & info2_flags_map[i].smb_fflag) {
4041                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
4042                             *stat_fflags |= info2_flags_map[i].stat_fflag;
4043                     } else {
4044                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4045                     }
4046             }
4047         }
4048
4049         /* If smb_fmask is asking to set any bits that are not supported by
4050          * our flag mappings, we should fail.
4051          */
4052         if ((smb_fmask & max_fmask) != smb_fmask) {
4053                 return False;
4054         }
4055
4056         return True;
4057 }
4058
4059
4060 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4061  * of file flags and birth (create) time.
4062  */
4063 static char *store_file_unix_basic_info2(connection_struct *conn,
4064                                 char *pdata,
4065                                 files_struct *fsp,
4066                                 const SMB_STRUCT_STAT *psbuf)
4067 {
4068         uint32 file_flags = 0;
4069         uint32 flags_mask = 0;
4070
4071         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4072
4073         /* Create (birth) time 64 bit */
4074         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4075         pdata += 8;
4076
4077         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4078         SIVAL(pdata, 0, file_flags); /* flags */
4079         SIVAL(pdata, 4, flags_mask); /* mask */
4080         pdata += 8;
4081
4082         return pdata;
4083 }
4084
4085 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4086                                      const struct stream_struct *streams,
4087                                      char *data,
4088                                      unsigned int max_data_bytes,
4089                                      unsigned int *data_size)
4090 {
4091         unsigned int i;
4092         unsigned int ofs = 0;
4093
4094         for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4095                 unsigned int next_offset;
4096                 size_t namelen;
4097                 smb_ucs2_t *namebuf;
4098
4099                 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4100                                       streams[i].name, &namelen) ||
4101                     namelen <= 2)
4102                 {
4103                         return NT_STATUS_INVALID_PARAMETER;
4104                 }
4105
4106                 /*
4107                  * name_buf is now null-terminated, we need to marshall as not
4108                  * terminated
4109                  */
4110
4111                 namelen -= 2;
4112
4113                 SIVAL(data, ofs+4, namelen);
4114                 SOFF_T(data, ofs+8, streams[i].size);
4115                 SOFF_T(data, ofs+16, streams[i].alloc_size);
4116                 memcpy(data+ofs+24, namebuf, namelen);
4117                 TALLOC_FREE(namebuf);
4118
4119                 next_offset = ofs + 24 + namelen;
4120
4121                 if (i == num_streams-1) {
4122                         SIVAL(data, ofs, 0);
4123                 }
4124                 else {
4125                         unsigned int align = ndr_align_size(next_offset, 8);
4126
4127                         memset(data+next_offset, 0, align);
4128                         next_offset += align;
4129
4130                         SIVAL(data, ofs, next_offset - ofs);
4131                         ofs = next_offset;
4132                 }
4133
4134                 ofs = next_offset;
4135         }
4136
4137         *data_size = ofs;
4138
4139         return NT_STATUS_OK;
4140 }
4141
4142 /****************************************************************************
4143  Reply to a TRANSACT2_QFILEINFO on a PIPE !
4144 ****************************************************************************/
4145
4146 static void call_trans2qpipeinfo(connection_struct *conn,
4147                                  struct smb_request *req,
4148                                  unsigned int tran_call,
4149                                  char **pparams, int total_params,
4150                                  char **ppdata, int total_data,
4151                                  unsigned int max_data_bytes)
4152 {
4153         char *params = *pparams;
4154         char *pdata = *ppdata;
4155         unsigned int data_size = 0;
4156         unsigned int param_size = 2;
4157         uint16 info_level;
4158         files_struct *fsp;
4159
4160         if (!params) {
4161                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4162                 return;
4163         }
4164
4165         if (total_params < 4) {
4166                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4167                 return;
4168         }
4169
4170         fsp = file_fsp(req, SVAL(params,0));
4171         if (!fsp_is_np(fsp)) {
4172                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4173                 return;
4174         }
4175
4176         info_level = SVAL(params,2);
4177
4178         *pparams = (char *)SMB_REALLOC(*pparams,2);
4179         if (*pparams == NULL) {
4180                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4181                 return;
4182         }
4183         params = *pparams;
4184         SSVAL(params,0,0);
4185         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4186         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4187         if (*ppdata == NULL ) {
4188                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4189                 return;
4190         }
4191         pdata = *ppdata;
4192
4193         switch (info_level) {
4194                 case SMB_FILE_STANDARD_INFORMATION:
4195                         memset(pdata,0,24);
4196                         SOFF_T(pdata,0,4096LL);
4197                         SIVAL(pdata,16,1);
4198                         SIVAL(pdata,20,1);
4199                         data_size = 24;
4200                         break;
4201
4202                 default:
4203                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4204                         return;
4205         }
4206
4207         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4208                             max_data_bytes);
4209
4210         return;
4211 }
4212
4213 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4214                                TALLOC_CTX *mem_ctx,
4215                                uint16_t info_level,
4216                                files_struct *fsp,
4217                                struct smb_filename *smb_fname,
4218                                bool delete_pending,
4219                                struct timespec write_time_ts,
4220                                struct ea_list *ea_list,
4221                                int lock_data_count,
4222                                char *lock_data,
4223                                uint16_t flags2,
4224                                unsigned int max_data_bytes,
4225                                char **ppdata,
4226                                unsigned int *pdata_size)
4227 {
4228         char *pdata = *ppdata;
4229         char *dstart, *dend;
4230         unsigned int data_size;
4231         struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4232         time_t create_time, mtime, atime, c_time;
4233         SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4234         char *p;
4235         char *base_name;
4236         char *dos_fname;
4237         int mode;
4238         int nlink;
4239         NTSTATUS status;
4240         uint64_t file_size = 0;
4241         uint64_t pos = 0;
4242         uint64_t allocation_size = 0;
4243         uint64_t file_index = 0;
4244         uint32_t access_mask = 0;
4245
4246         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4247                 return NT_STATUS_INVALID_LEVEL;
4248         }
4249
4250         DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4251                  smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4252                  info_level, max_data_bytes));
4253
4254         mode = dos_mode(conn, smb_fname);
4255         nlink = psbuf->st_ex_nlink;
4256
4257         if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4258                 nlink = 1;
4259         }
4260
4261         if ((nlink > 0) && delete_pending) {
4262                 nlink -= 1;
4263         }
4264
4265         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4266         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4267         if (*ppdata == NULL) {
4268                 return NT_STATUS_NO_MEMORY;
4269         }
4270         pdata = *ppdata;
4271         dstart = pdata;
4272         dend = dstart + data_size - 1;
4273
4274         if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4275                 update_stat_ex_mtime(psbuf, write_time_ts);
4276         }
4277
4278         create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4279         mtime_ts = psbuf->st_ex_mtime;
4280         atime_ts = psbuf->st_ex_atime;
4281         ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4282
4283         if (lp_dos_filetime_resolution(SNUM(conn))) {
4284                 dos_filetime_timespec(&create_time_ts);
4285                 dos_filetime_timespec(&mtime_ts);
4286                 dos_filetime_timespec(&atime_ts);
4287                 dos_filetime_timespec(&ctime_ts);
4288         }
4289
4290         create_time = convert_timespec_to_time_t(create_time_ts);
4291         mtime = convert_timespec_to_time_t(mtime_ts);
4292         atime = convert_timespec_to_time_t(atime_ts);
4293         c_time = convert_timespec_to_time_t(ctime_ts);
4294
4295         p = strrchr_m(smb_fname->base_name,'/');
4296         if (!p)
4297                 base_name = smb_fname->base_name;
4298         else
4299                 base_name = p+1;
4300
4301         /* NT expects the name to be in an exact form of the *full*
4302            filename. See the trans2 torture test */
4303         if (ISDOT(base_name)) {
4304                 dos_fname = talloc_strdup(mem_ctx, "\\");
4305                 if (!dos_fname) {
4306                         return NT_STATUS_NO_MEMORY;
4307                 }
4308         } else {
4309                 dos_fname = talloc_asprintf(mem_ctx,
4310                                 "\\%s",
4311                                 smb_fname->base_name);
4312                 if (!dos_fname) {
4313                         return NT_STATUS_NO_MEMORY;
4314                 }
4315                 if (is_ntfs_stream_smb_fname(smb_fname)) {
4316                         dos_fname = talloc_asprintf(dos_fname, "%s",
4317                                                     smb_fname->stream_name);
4318                         if (!dos_fname) {
4319                                 return NT_STATUS_NO_MEMORY;
4320                         }
4321                 }
4322
4323                 string_replace(dos_fname, '/', '\\');
4324         }
4325
4326         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4327
4328         if (!fsp) {
4329                 /* Do we have this path open ? */
4330                 files_struct *fsp1;
4331                 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4332                 fsp1 = file_find_di_first(conn->sconn, fileid);
4333                 if (fsp1 && fsp1->initial_allocation_size) {
4334                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4335                 }
4336         }
4337
4338         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4339                 file_size = get_file_size_stat(psbuf);
4340         }
4341
4342         if (fsp) {
4343                 pos = fsp->fh->position_information;
4344         }
4345
4346         if (fsp) {
4347                 access_mask = fsp->access_mask;
4348         } else {
4349                 /* GENERIC_EXECUTE mapping from Windows */
4350                 access_mask = 0x12019F;
4351         }
4352
4353         /* This should be an index number - looks like
4354            dev/ino to me :-)
4355
4356            I think this causes us to fail the IFSKIT
4357            BasicFileInformationTest. -tpot */
4358         file_index = get_FileIndex(conn, psbuf);
4359
4360         switch (info_level) {
4361                 case SMB_INFO_STANDARD:
4362                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4363                         data_size = 22;
4364                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4365                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4366                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4367                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
4368                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4369                         SSVAL(pdata,l1_attrFile,mode);
4370                         break;
4371
4372                 case SMB_INFO_QUERY_EA_SIZE:
4373                 {
4374                         unsigned int ea_size =
4375                             estimate_ea_size(conn, fsp,
4376                                              smb_fname->base_name);
4377                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4378                         data_size = 26;
4379                         srv_put_dos_date2(pdata,0,create_time);
4380                         srv_put_dos_date2(pdata,4,atime);
4381                         srv_put_dos_date2(pdata,8,mtime); /* write time */
4382                         SIVAL(pdata,12,(uint32)file_size);
4383                         SIVAL(pdata,16,(uint32)allocation_size);
4384                         SSVAL(pdata,20,mode);
4385                         SIVAL(pdata,22,ea_size);
4386                         break;
4387                 }
4388
4389                 case SMB_INFO_IS_NAME_VALID:
4390                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4391                         if (fsp) {
4392                                 /* os/2 needs this ? really ?*/
4393                                 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4394                         }
4395                         /* This is only reached for qpathinfo */
4396                         data_size = 0;
4397                         break;
4398
4399                 case SMB_INFO_QUERY_EAS_FROM_LIST:
4400                 {
4401                         size_t total_ea_len = 0;
4402                         struct ea_list *ea_file_list = NULL;
4403
4404                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4405
4406                         ea_file_list =
4407                             get_ea_list_from_file(mem_ctx, conn, fsp,
4408                                                   smb_fname->base_name,
4409                                                   &total_ea_len);
4410                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4411
4412                         if (!ea_list || (total_ea_len > data_size)) {
4413                                 data_size = 4;
4414                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4415                                 break;
4416                         }
4417
4418                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4419                         break;
4420                 }
4421
4422                 case SMB_INFO_QUERY_ALL_EAS:
4423                 {
4424                         /* We have data_size bytes to put EA's into. */
4425                         size_t total_ea_len = 0;
4426
4427                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4428
4429                         ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4430                                                         smb_fname->base_name,
4431                                                         &total_ea_len);
4432                         if (!ea_list || (total_ea_len > data_size)) {
4433                                 data_size = 4;
4434                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4435                                 break;
4436                         }
4437
4438                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4439                         break;
4440                 }
4441
4442                 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4443                 {
4444                         /* This is FileFullEaInformation - 0xF which maps to
4445                          * 1015 (decimal) in smbd_do_setfilepathinfo. */
4446
4447                         /* We have data_size bytes to put EA's into. */
4448                         size_t total_ea_len = 0;
4449                         struct ea_list *ea_file_list = NULL;
4450
4451                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4452
4453                         /*TODO: add filtering and index handling */
4454
4455                         ea_file_list =
4456                             get_ea_list_from_file(mem_ctx, conn, fsp,
4457                                                   smb_fname->base_name,
4458                                                   &total_ea_len);
4459                         if (!ea_file_list) {
4460                                 return NT_STATUS_NO_EAS_ON_FILE;
4461                         }
4462
4463                         status = fill_ea_chained_buffer(mem_ctx,
4464                                                         pdata,
4465                                                         data_size,
4466                                                         &data_size,
4467                                                         conn, ea_file_list);
4468                         if (!NT_STATUS_IS_OK(status)) {
4469                                 return status;
4470                         }
4471                         break;
4472                 }
4473
4474                 case SMB_FILE_BASIC_INFORMATION:
4475                 case SMB_QUERY_FILE_BASIC_INFO:
4476
4477                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4478                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4479                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4480                         } else {
4481                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4482                                 data_size = 40;
4483                                 SIVAL(pdata,36,0);
4484                         }
4485                         put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4486                         put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4487                         put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4488                         put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4489                         SIVAL(pdata,32,mode);
4490
4491                         DEBUG(5,("SMB_QFBI - "));
4492                         DEBUG(5,("create: %s ", ctime(&create_time)));
4493                         DEBUG(5,("access: %s ", ctime(&atime)));
4494                         DEBUG(5,("write: %s ", ctime(&mtime)));
4495                         DEBUG(5,("change: %s ", ctime(&c_time)));
4496                         DEBUG(5,("mode: %x\n", mode));
4497                         break;
4498
4499                 case SMB_FILE_STANDARD_INFORMATION:
4500                 case SMB_QUERY_FILE_STANDARD_INFO:
4501
4502                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4503                         data_size = 24;
4504                         SOFF_T(pdata,0,allocation_size);
4505                         SOFF_T(pdata,8,file_size);
4506                         SIVAL(pdata,16,nlink);
4507                         SCVAL(pdata,20,delete_pending?1:0);
4508                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4509                         SSVAL(pdata,22,0); /* Padding. */
4510                         break;
4511
4512                 case SMB_FILE_EA_INFORMATION:
4513                 case SMB_QUERY_FILE_EA_INFO:
4514                 {
4515                         unsigned int ea_size =
4516                             estimate_ea_size(conn, fsp, smb_fname->base_name);
4517                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4518                         data_size = 4;
4519                         SIVAL(pdata,0,ea_size);
4520                         break;
4521                 }
4522
4523                 /* Get the 8.3 name - used if NT SMB was negotiated. */
4524                 case SMB_QUERY_FILE_ALT_NAME_INFO:
4525                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4526                 {
4527                         int len;
4528                         char mangled_name[13];
4529                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4530                         if (!name_to_8_3(base_name,mangled_name,
4531                                                 True,conn->params)) {
4532                                 return NT_STATUS_NO_MEMORY;
4533                         }
4534                         len = srvstr_push(dstart, flags2,
4535                                           pdata+4, mangled_name,
4536                                           PTR_DIFF(dend, pdata+4),
4537                                           STR_UNICODE);
4538                         data_size = 4 + len;
4539                         SIVAL(pdata,0,len);
4540                         break;
4541                 }
4542
4543                 case SMB_QUERY_FILE_NAME_INFO:
4544                 {
4545                         int len;
4546                         /*
4547                           this must be *exactly* right for ACLs on mapped drives to work
4548                          */
4549                         len = srvstr_push(dstart, flags2,
4550                                           pdata+4, dos_fname,
4551                                           PTR_DIFF(dend, pdata+4),
4552                                           STR_UNICODE);
4553                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4554                         data_size = 4 + len;
4555                         SIVAL(pdata,0,len);
4556                         break;
4557                 }
4558
4559                 case SMB_FILE_ALLOCATION_INFORMATION:
4560                 case SMB_QUERY_FILE_ALLOCATION_INFO:
4561                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4562                         data_size = 8;
4563                         SOFF_T(pdata,0,allocation_size);
4564                         break;
4565
4566                 case SMB_FILE_END_OF_FILE_INFORMATION:
4567                 case SMB_QUERY_FILE_END_OF_FILEINFO:
4568                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4569                         data_size = 8;
4570                         SOFF_T(pdata,0,file_size);
4571                         break;
4572
4573                 case SMB_QUERY_FILE_ALL_INFO:
4574                 case SMB_FILE_ALL_INFORMATION:
4575                 {
4576                         int len;
4577                         unsigned int ea_size =
4578                             estimate_ea_size(conn, fsp, smb_fname->base_name);
4579                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4580                         put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4581                         put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4582                         put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4583                         put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4584                         SIVAL(pdata,32,mode);
4585                         SIVAL(pdata,36,0); /* padding. */
4586                         pdata += 40;
4587                         SOFF_T(pdata,0,allocation_size);
4588                         SOFF_T(pdata,8,file_size);
4589                         SIVAL(pdata,16,nlink);
4590                         SCVAL(pdata,20,delete_pending);
4591                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4592                         SSVAL(pdata,22,0);
4593                         pdata += 24;
4594                         SIVAL(pdata,0,ea_size);
4595                         pdata += 4; /* EA info */
4596                         len = srvstr_push(dstart, flags2,
4597                                           pdata+4, dos_fname,
4598                                           PTR_DIFF(dend, pdata+4),
4599                                           STR_UNICODE);
4600                         SIVAL(pdata,0,len);
4601                         pdata += 4 + len;
4602                         data_size = PTR_DIFF(pdata,(*ppdata));
4603                         break;
4604                 }
4605
4606                 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4607                 {
4608                         int len;
4609                         unsigned int ea_size =
4610                             estimate_ea_size(conn, fsp, smb_fname->base_name);
4611                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4612                         put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4613                         put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4614                         put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4615                         put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4616                         SIVAL(pdata,    0x20, mode);
4617                         SIVAL(pdata,    0x24, 0); /* padding. */
4618                         SBVAL(pdata,    0x28, allocation_size);
4619                         SBVAL(pdata,    0x30, file_size);
4620                         SIVAL(pdata,    0x38, nlink);
4621                         SCVAL(pdata,    0x3C, delete_pending);
4622                         SCVAL(pdata,    0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4623                         SSVAL(pdata,    0x3E, 0); /* padding */
4624                         SBVAL(pdata,    0x40, file_index);
4625                         SIVAL(pdata,    0x48, ea_size);
4626                         SIVAL(pdata,    0x4C, access_mask);
4627                         SBVAL(pdata,    0x50, pos);
4628                         SIVAL(pdata,    0x58, mode); /*TODO: mode != mode fix this!!! */
4629                         SIVAL(pdata,    0x5C, 0); /* No alignment needed. */
4630
4631                         pdata += 0x60;
4632
4633                         len = srvstr_push(dstart, flags2,
4634                                           pdata+4, dos_fname,
4635                                           PTR_DIFF(dend, pdata+4),
4636                                           STR_UNICODE);
4637                         SIVAL(pdata,0,len);
4638                         pdata += 4 + len;
4639                         data_size = PTR_DIFF(pdata,(*ppdata));
4640                         break;
4641                 }
4642                 case SMB_FILE_INTERNAL_INFORMATION:
4643
4644                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4645                         SBVAL(pdata, 0, file_index);
4646                         data_size = 8;
4647                         break;
4648
4649                 case SMB_FILE_ACCESS_INFORMATION:
4650                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4651                         SIVAL(pdata, 0, access_mask);
4652                         data_size = 4;
4653                         break;
4654
4655                 case SMB_FILE_NAME_INFORMATION:
4656                         /* Pathname with leading '\'. */
4657                         {
4658                                 size_t byte_len;
4659                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4660                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4661                                 SIVAL(pdata,0,byte_len);
4662                                 data_size = 4 + byte_len;
4663                                 break;
4664                         }
4665
4666                 case SMB_FILE_DISPOSITION_INFORMATION:
4667                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4668                         data_size = 1;
4669                         SCVAL(pdata,0,delete_pending);
4670                         break;
4671
4672                 case SMB_FILE_POSITION_INFORMATION:
4673                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4674                         data_size = 8;
4675                         SOFF_T(pdata,0,pos);
4676                         break;
4677
4678                 case SMB_FILE_MODE_INFORMATION:
4679                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4680                         SIVAL(pdata,0,mode);
4681                         data_size = 4;
4682                         break;
4683
4684                 case SMB_FILE_ALIGNMENT_INFORMATION:
4685                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4686                         SIVAL(pdata,0,0); /* No alignment needed. */
4687                         data_size = 4;
4688                         break;
4689
4690                 /*
4691                  * NT4 server just returns "invalid query" to this - if we try
4692                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
4693                  * want this. JRA.
4694                  */
4695                 /* The first statement above is false - verified using Thursby
4696                  * client against NT4 -- gcolley.
4697                  */
4698                 case SMB_QUERY_FILE_STREAM_INFO:
4699                 case SMB_FILE_STREAM_INFORMATION: {
4700                         unsigned int num_streams = 0;
4701                         struct stream_struct *streams = NULL;
4702
4703                         DEBUG(10,("smbd_do_qfilepathinfo: "
4704                                   "SMB_FILE_STREAM_INFORMATION\n"));
4705
4706                         if (is_ntfs_stream_smb_fname(smb_fname)) {
4707                                 return NT_STATUS_INVALID_PARAMETER;
4708                         }
4709
4710                         status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4711                                                 talloc_tos(), &num_streams, &streams);
4712
4713                         if (!NT_STATUS_IS_OK(status)) {
4714                                 DEBUG(10, ("could not get stream info: %s\n",
4715                                            nt_errstr(status)));
4716                                 return status;
4717                         }
4718
4719                         status = marshall_stream_info(num_streams, streams,
4720                                                       pdata, max_data_bytes,
4721                                                       &data_size);
4722
4723                         if (!NT_STATUS_IS_OK(status)) {
4724                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
4725                                            nt_errstr(status)));
4726                                 return status;
4727                         }
4728
4729                         TALLOC_FREE(streams);
4730
4731                         break;
4732                 }
4733                 case SMB_QUERY_COMPRESSION_INFO:
4734                 case SMB_FILE_COMPRESSION_INFORMATION:
4735                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4736                         SOFF_T(pdata,0,file_size);
4737                         SIVAL(pdata,8,0); /* ??? */
4738                         SIVAL(pdata,12,0); /* ??? */
4739                         data_size = 16;
4740                         break;
4741
4742                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4743                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4744                         put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4745                         put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4746                         put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4747                         put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4748                         SOFF_T(pdata,32,allocation_size);
4749                         SOFF_T(pdata,40,file_size);
4750                         SIVAL(pdata,48,mode);
4751                         SIVAL(pdata,52,0); /* ??? */
4752                         data_size = 56;
4753                         break;
4754
4755                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4756                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4757                         SIVAL(pdata,0,mode);
4758                         SIVAL(pdata,4,0);
4759                         data_size = 8;
4760                         break;
4761
4762                 /*
4763                  * CIFS UNIX Extensions.
4764                  */
4765
4766                 case SMB_QUERY_FILE_UNIX_BASIC:
4767
4768                         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4769                         data_size = PTR_DIFF(pdata,(*ppdata));
4770
4771                         DEBUG(4,("smbd_do_qfilepathinfo: "
4772                                  "SMB_QUERY_FILE_UNIX_BASIC\n"));
4773                         dump_data(4, (uint8_t *)(*ppdata), data_size);
4774
4775                         break;
4776
4777                 case SMB_QUERY_FILE_UNIX_INFO2:
4778
4779                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4780                         data_size = PTR_DIFF(pdata,(*ppdata));
4781
4782                         {
4783                                 int i;
4784                                 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4785
4786                                 for (i=0; i<100; i++)
4787                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4788                                 DEBUG(4,("\n"));
4789                         }
4790
4791                         break;
4792
4793                 case SMB_QUERY_FILE_UNIX_LINK:
4794                         {
4795                                 int len;
4796                                 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4797
4798                                 if (!buffer) {
4799                                         return NT_STATUS_NO_MEMORY;
4800                                 }
4801
4802                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4803 #ifdef S_ISLNK
4804                                 if(!S_ISLNK(psbuf->st_ex_mode)) {
4805                                         return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4806                                 }
4807 #else
4808                                 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4809 #endif
4810                                 len = SMB_VFS_READLINK(conn,
4811                                                        smb_fname->base_name,
4812                                                        buffer, PATH_MAX);
4813                                 if (len == -1) {
4814                                         return map_nt_error_from_unix(errno);
4815                                 }
4816                                 buffer[len] = 0;
4817                                 len = srvstr_push(dstart, flags2,
4818                                                   pdata, buffer,
4819                                                   PTR_DIFF(dend, pdata),
4820                                                   STR_TERMINATE);
4821                                 pdata += len;
4822                                 data_size = PTR_DIFF(pdata,(*ppdata));
4823
4824                                 break;
4825                         }
4826
4827 #if defined(HAVE_POSIX_ACLS)
4828                 case SMB_QUERY_POSIX_ACL:
4829                         {
4830                                 SMB_ACL_T file_acl = NULL;
4831                                 SMB_ACL_T def_acl = NULL;
4832                                 uint16 num_file_acls = 0;
4833                                 uint16 num_def_acls = 0;
4834
4835                                 if (fsp && fsp->fh->fd != -1) {
4836                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4837                                 } else {
4838                                         file_acl =
4839                                             SMB_VFS_SYS_ACL_GET_FILE(conn,
4840                                                 smb_fname->base_name,
4841                                                 SMB_ACL_TYPE_ACCESS);
4842                                 }
4843
4844                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4845                                         DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4846                                                  "not implemented on "
4847                                                  "filesystem containing %s\n",
4848                                                  smb_fname->base_name));
4849                                         return NT_STATUS_NOT_IMPLEMENTED;
4850                                 }
4851
4852                                 if (S_ISDIR(psbuf->st_ex_mode)) {
4853                                         if (fsp && fsp->is_directory) {
4854                                                 def_acl =
4855                                                     SMB_VFS_SYS_ACL_GET_FILE(
4856                                                             conn,
4857                                                             fsp->fsp_name->base_name,
4858                                                             SMB_ACL_TYPE_DEFAULT);
4859                                         } else {
4860                                                 def_acl =
4861                                                     SMB_VFS_SYS_ACL_GET_FILE(
4862                                                             conn,
4863                                                             smb_fname->base_name,
4864                                                             SMB_ACL_TYPE_DEFAULT);
4865                                         }
4866                                         def_acl = free_empty_sys_acl(conn, def_acl);
4867                                 }
4868
4869                                 num_file_acls = count_acl_entries(conn, file_acl);
4870                                 num_def_acls = count_acl_entries(conn, def_acl);
4871
4872                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4873                                         DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4874                                                 data_size,
4875                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4876                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4877                                         if (file_acl) {
4878                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4879                                         }
4880                                         if (def_acl) {
4881                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4882                                         }
4883                                         return NT_STATUS_BUFFER_TOO_SMALL;
4884                                 }
4885
4886                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4887                                 SSVAL(pdata,2,num_file_acls);
4888                                 SSVAL(pdata,4,num_def_acls);
4889                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4890                                         if (file_acl) {
4891                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4892                                         }
4893                                         if (def_acl) {
4894                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4895                                         }
4896                                         return NT_STATUS_INTERNAL_ERROR;
4897                                 }
4898                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4899                                         if (file_acl) {
4900                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4901                                         }
4902                                         if (def_acl) {
4903                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4904                                         }
4905                                         return NT_STATUS_INTERNAL_ERROR;
4906                                 }
4907
4908                                 if (file_acl) {
4909                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4910                                 }
4911                                 if (def_acl) {
4912                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4913                                 }
4914                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4915                                 break;
4916                         }
4917 #endif
4918
4919
4920                 case SMB_QUERY_POSIX_LOCK:
4921                 {
4922                         uint64_t count;
4923                         uint64_t offset;
4924                         uint64_t smblctx;
4925                         enum brl_type lock_type;
4926
4927                         /* We need an open file with a real fd for this. */
4928                         if (!fsp || fsp->fh->fd == -1) {
4929                                 return NT_STATUS_INVALID_LEVEL;
4930                         }
4931
4932                         if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4933                                 return NT_STATUS_INVALID_PARAMETER;
4934                         }
4935
4936                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4937                                 case POSIX_LOCK_TYPE_READ:
4938                                         lock_type = READ_LOCK;
4939                                         break;
4940                                 case POSIX_LOCK_TYPE_WRITE:
4941                                         lock_type = WRITE_LOCK;
4942                                         break;
4943                                 case POSIX_LOCK_TYPE_UNLOCK:
4944                                 default:
4945                                         /* There's no point in asking for an unlock... */
4946                                         return NT_STATUS_INVALID_PARAMETER;
4947                         }
4948
4949                         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4950 #if defined(HAVE_LONGLONG)
4951                         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4952                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4953                         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4954                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4955 #else /* HAVE_LONGLONG */
4956                         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4957                         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4958 #endif /* HAVE_LONGLONG */
4959
4960                         status = query_lock(fsp,
4961                                         &smblctx,
4962                                         &count,
4963                                         &offset,
4964                                         &lock_type,
4965                                         POSIX_LOCK);
4966
4967                         if (ERROR_WAS_LOCK_DENIED(status)) {
4968                                 /* Here we need to report who has it locked... */
4969                                 data_size = POSIX_LOCK_DATA_SIZE;
4970
4971                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4972                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4973                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4974 #if defined(HAVE_LONGLONG)
4975                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4976                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4977                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4978                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4979 #else /* HAVE_LONGLONG */
4980                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4981                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4982 #endif /* HAVE_LONGLONG */
4983
4984                         } else if (NT_STATUS_IS_OK(status)) {
4985                                 /* For success we just return a copy of what we sent
4986                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4987                                 data_size = POSIX_LOCK_DATA_SIZE;
4988                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4989                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4990                         } else {
4991                                 return status;
4992                         }
4993                         break;
4994                 }
4995
4996                 default:
4997                         return NT_STATUS_INVALID_LEVEL;
4998         }
4999
5000         *pdata_size = data_size;
5001         return NT_STATUS_OK;
5002 }
5003
5004 /****************************************************************************
5005  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5006  file name or file id).
5007 ****************************************************************************/
5008
5009 static void call_trans2qfilepathinfo(connection_struct *conn,
5010                                      struct smb_request *req,
5011                                      unsigned int tran_call,
5012                                      char **pparams, int total_params,
5013                                      char **ppdata, int total_data,
5014                                      unsigned int max_data_bytes)
5015 {
5016         char *params = *pparams;
5017         char *pdata = *ppdata;
5018         uint16 info_level;
5019         unsigned int data_size = 0;
5020         unsigned int param_size = 2;
5021         struct smb_filename *smb_fname = NULL;
5022         bool delete_pending = False;
5023         struct timespec write_time_ts;
5024         files_struct *fsp = NULL;
5025         struct file_id fileid;
5026         struct ea_list *ea_list = NULL;
5027         int lock_data_count = 0;
5028         char *lock_data = NULL;
5029         NTSTATUS status = NT_STATUS_OK;
5030
5031         if (!params) {
5032                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5033                 return;
5034         }
5035
5036         ZERO_STRUCT(write_time_ts);
5037
5038         if (tran_call == TRANSACT2_QFILEINFO) {
5039                 if (total_params < 4) {
5040                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5041                         return;
5042                 }
5043
5044                 if (IS_IPC(conn)) {
5045                         call_trans2qpipeinfo(conn, req, tran_call,
5046                                              pparams, total_params,
5047                                              ppdata, total_data,
5048                                              max_data_bytes);
5049                         return;
5050                 }
5051
5052                 fsp = file_fsp(req, SVAL(params,0));
5053                 info_level = SVAL(params,2);
5054
5055                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5056
5057                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5058                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5059                         return;
5060                 }
5061
5062                 /* Initial check for valid fsp ptr. */
5063                 if (!check_fsp_open(conn, req, fsp)) {
5064                         return;
5065                 }
5066
5067                 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5068                                            &smb_fname);
5069                 if (!NT_STATUS_IS_OK(status)) {
5070                         reply_nterror(req, status);
5071                         return;
5072                 }
5073
5074                 if(fsp->fake_file_handle) {
5075                         /*
5076                          * This is actually for the QUOTA_FAKE_FILE --metze
5077                          */
5078
5079                         /* We know this name is ok, it's already passed the checks. */
5080
5081                 } else if(fsp->fh->fd == -1) {
5082                         /*
5083                          * This is actually a QFILEINFO on a directory
5084                          * handle (returned from an NT SMB). NT5.0 seems
5085                          * to do this call. JRA.
5086                          */
5087
5088                         if (INFO_LEVEL_IS_UNIX(info_level)) {
5089                                 /* Always do lstat for UNIX calls. */
5090                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5091                                         DEBUG(3,("call_trans2qfilepathinfo: "
5092                                                  "SMB_VFS_LSTAT of %s failed "
5093                                                  "(%s)\n",
5094                                                  smb_fname_str_dbg(smb_fname),
5095                                                  strerror(errno)));
5096                                         reply_nterror(req,
5097                                                 map_nt_error_from_unix(errno));
5098                                         return;
5099                                 }
5100                         } else if (SMB_VFS_STAT(conn, smb_fname)) {
5101                                 DEBUG(3,("call_trans2qfilepathinfo: "
5102                                          "SMB_VFS_STAT of %s failed (%s)\n",
5103                                          smb_fname_str_dbg(smb_fname),
5104                                          strerror(errno)));
5105                                 reply_nterror(req,
5106                                         map_nt_error_from_unix(errno));
5107                                 return;
5108                         }
5109
5110                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5111                         get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5112                 } else {
5113                         /*
5114                          * Original code - this is an open file.
5115                          */
5116                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5117                                 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5118                                           fsp->fnum, strerror(errno)));
5119                                 reply_nterror(req,
5120                                         map_nt_error_from_unix(errno));
5121                                 return;
5122                         }
5123                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5124                         get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5125                 }
5126
5127         } else {
5128                 uint32_t name_hash;
5129                 char *fname = NULL;
5130                 uint32_t ucf_flags = 0;
5131
5132                 /* qpathinfo */
5133                 if (total_params < 7) {
5134                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5135                         return;
5136                 }
5137
5138                 info_level = SVAL(params,0);
5139
5140                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5141
5142                 if (INFO_LEVEL_IS_UNIX(info_level)) {
5143                         if (!lp_unix_extensions()) {
5144                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5145                                 return;
5146                         }
5147                         if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5148                                         info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5149                                         info_level == SMB_QUERY_FILE_UNIX_LINK) {
5150                                 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5151                         }
5152                 }
5153
5154                 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5155                                 total_params - 6,
5156                                 STR_TERMINATE, &status);
5157                 if (!NT_STATUS_IS_OK(status)) {
5158                         reply_nterror(req, status);
5159                         return;
5160                 }
5161
5162                 status = filename_convert(req,
5163                                         conn,
5164                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
5165                                         fname,
5166                                         ucf_flags,
5167                                         NULL,
5168                                         &smb_fname);
5169                 if (!NT_STATUS_IS_OK(status)) {
5170                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5171                                 reply_botherror(req,
5172                                                 NT_STATUS_PATH_NOT_COVERED,
5173                                                 ERRSRV, ERRbadpath);
5174                                 return;
5175                         }
5176                         reply_nterror(req, status);
5177                         return;
5178                 }
5179
5180                 /* If this is a stream, check if there is a delete_pending. */
5181                 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5182                     && is_ntfs_stream_smb_fname(smb_fname)) {
5183                         struct smb_filename *smb_fname_base = NULL;
5184
5185                         /* Create an smb_filename with stream_name == NULL. */
5186                         status =
5187                             create_synthetic_smb_fname(talloc_tos(),
5188                                                        smb_fname->base_name,
5189                                                        NULL, NULL,
5190                                                        &smb_fname_base);
5191                         if (!NT_STATUS_IS_OK(status)) {
5192                                 reply_nterror(req, status);
5193                                 return;
5194                         }
5195
5196                         if (INFO_LEVEL_IS_UNIX(info_level)) {
5197                                 /* Always do lstat for UNIX calls. */
5198                                 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5199                                         DEBUG(3,("call_trans2qfilepathinfo: "
5200                                                  "SMB_VFS_LSTAT of %s failed "
5201                                                  "(%s)\n",
5202                                                  smb_fname_str_dbg(smb_fname_base),
5203                                                  strerror(errno)));
5204                                         TALLOC_FREE(smb_fname_base);
5205                                         reply_nterror(req,
5206                                                 map_nt_error_from_unix(errno));
5207                                         return;
5208                                 }
5209                         } else {
5210                                 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5211                                         DEBUG(3,("call_trans2qfilepathinfo: "
5212                                                  "fileinfo of %s failed "
5213                                                  "(%s)\n",
5214                                                  smb_fname_str_dbg(smb_fname_base),
5215                                                  strerror(errno)));
5216                                         TALLOC_FREE(smb_fname_base);
5217                                         reply_nterror(req,
5218                                                 map_nt_error_from_unix(errno));
5219                                         return;
5220                                 }
5221                         }
5222
5223                         status = file_name_hash(conn,
5224                                         smb_fname_str_dbg(smb_fname_base),
5225                                         &name_hash);
5226                         if (!NT_STATUS_IS_OK(status)) {
5227                                 TALLOC_FREE(smb_fname_base);
5228                                 reply_nterror(req, status);
5229                                 return;
5230                         }
5231
5232                         fileid = vfs_file_id_from_sbuf(conn,
5233                                                        &smb_fname_base->st);
5234                         TALLOC_FREE(smb_fname_base);
5235                         get_file_infos(fileid, name_hash, &delete_pending, NULL);
5236                         if (delete_pending) {
5237                                 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5238                                 return;
5239                         }
5240                 }
5241
5242                 if (INFO_LEVEL_IS_UNIX(info_level)) {
5243                         /* Always do lstat for UNIX calls. */
5244                         if (SMB_VFS_LSTAT(conn, smb_fname)) {
5245                                 DEBUG(3,("call_trans2qfilepathinfo: "
5246                                          "SMB_VFS_LSTAT of %s failed (%s)\n",
5247                                          smb_fname_str_dbg(smb_fname),
5248                                          strerror(errno)));
5249                                 reply_nterror(req,
5250                                         map_nt_error_from_unix(errno));
5251                                 return;
5252                         }
5253
5254                 } else {
5255                         if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5256                                 DEBUG(3,("call_trans2qfilepathinfo: "
5257                                          "SMB_VFS_STAT of %s failed (%s)\n",
5258                                          smb_fname_str_dbg(smb_fname),
5259                                          strerror(errno)));
5260                                 reply_nterror(req,
5261                                         map_nt_error_from_unix(errno));
5262                                 return;
5263                         }
5264                 }
5265
5266                 status = file_name_hash(conn,
5267                                 smb_fname_str_dbg(smb_fname),
5268                                 &name_hash);
5269                 if (!NT_STATUS_IS_OK(status)) {
5270                         reply_nterror(req, status);
5271                         return;
5272                 }
5273
5274                 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5275                 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5276                 if (delete_pending) {
5277                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
5278                         return;
5279                 }
5280         }
5281
5282         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5283                  "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5284                  fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5285
5286         /* Pull out any data sent here before we realloc. */
5287         switch (info_level) {
5288                 case SMB_INFO_QUERY_EAS_FROM_LIST:
5289                 {
5290                         /* Pull any EA list from the data portion. */
5291                         uint32 ea_size;
5292
5293                         if (total_data < 4) {
5294                                 reply_nterror(
5295                                         req, NT_STATUS_INVALID_PARAMETER);
5296                                 return;
5297                         }
5298                         ea_size = IVAL(pdata,0);
5299
5300                         if (total_data > 0 && ea_size != total_data) {
5301                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5302 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5303                                 reply_nterror(
5304                                         req, NT_STATUS_INVALID_PARAMETER);
5305                                 return;
5306                         }
5307
5308                         if (!lp_ea_support(SNUM(conn))) {
5309                                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5310                                 return;
5311                         }
5312
5313                         /* Pull out the list of names. */
5314                         ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5315                         if (!ea_list) {
5316                                 reply_nterror(
5317                                         req, NT_STATUS_INVALID_PARAMETER);
5318                                 return;
5319                         }
5320                         break;
5321                 }
5322
5323                 case SMB_QUERY_POSIX_LOCK:
5324                 {
5325                         if (fsp == NULL || fsp->fh->fd == -1) {
5326                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5327                                 return;
5328                         }
5329
5330                         if (total_data != POSIX_LOCK_DATA_SIZE) {
5331                                 reply_nterror(
5332                                         req, NT_STATUS_INVALID_PARAMETER);
5333                                 return;
5334                         }
5335
5336                         /* Copy the lock range data. */
5337                         lock_data = (char *)talloc_memdup(
5338                                 req, pdata, total_data);
5339                         if (!lock_data) {
5340                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5341                                 return;
5342                         }
5343                         lock_data_count = total_data;
5344                 }
5345                 default:
5346                         break;
5347         }
5348
5349         *pparams = (char *)SMB_REALLOC(*pparams,2);
5350         if (*pparams == NULL) {
5351                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5352                 return;
5353         }
5354         params = *pparams;
5355         SSVAL(params,0,0);
5356
5357         /*
5358          * draft-leach-cifs-v1-spec-02.txt
5359          * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5360          * says:
5361          *
5362          *  The requested information is placed in the Data portion of the
5363          *  transaction response. For the information levels greater than 0x100,
5364          *  the transaction response has 1 parameter word which should be
5365          *  ignored by the client.
5366          *
5367          * However Windows only follows this rule for the IS_NAME_VALID call.
5368          */
5369         switch (info_level) {
5370         case SMB_INFO_IS_NAME_VALID:
5371                 param_size = 0;
5372                 break;
5373         }
5374
5375         if ((info_level & 0xFF00) == 0xFF00) {
5376                 /*
5377                  * We use levels that start with 0xFF00
5378                  * internally to represent SMB2 specific levels
5379                  */
5380                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5381                 return;
5382         }
5383
5384         status = smbd_do_qfilepathinfo(conn, req, info_level,
5385                                        fsp, smb_fname,
5386                                        delete_pending, write_time_ts,
5387                                        ea_list,
5388                                        lock_data_count, lock_data,
5389                                        req->flags2, max_data_bytes,
5390                                        ppdata, &data_size);
5391         if (!NT_STATUS_IS_OK(status)) {
5392                 reply_nterror(req, status);
5393                 return;
5394         }
5395
5396         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5397                             max_data_bytes);
5398
5399         return;
5400 }
5401
5402 /****************************************************************************
5403  Set a hard link (called by UNIX extensions and by NT rename with HARD link
5404  code.
5405 ****************************************************************************/
5406
5407 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5408                 connection_struct *conn,
5409                 struct smb_request *req,
5410                 bool overwrite_if_exists,
5411                 const struct smb_filename *smb_fname_old,
5412                 struct smb_filename *smb_fname_new)
5413 {
5414         NTSTATUS status = NT_STATUS_OK;
5415
5416         /* source must already exist. */
5417         if (!VALID_STAT(smb_fname_old->st)) {
5418                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5419         }
5420
5421         if (VALID_STAT(smb_fname_new->st)) {
5422                 if (overwrite_if_exists) {
5423                         if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5424                                 return NT_STATUS_FILE_IS_A_DIRECTORY;
5425                         }
5426                         status = unlink_internals(conn,
5427                                                 req,
5428                                                 FILE_ATTRIBUTE_NORMAL,
5429                                                 smb_fname_new,
5430                                                 false);
5431                         if (!NT_STATUS_IS_OK(status)) {
5432                                 return status;
5433                         }
5434                 } else {
5435                         /* Disallow if newname already exists. */
5436                         return NT_STATUS_OBJECT_NAME_COLLISION;
5437                 }
5438         }
5439
5440         /* No links from a directory. */
5441         if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5442                 return NT_STATUS_FILE_IS_A_DIRECTORY;
5443         }
5444
5445         /* Setting a hardlink to/from a stream isn't currently supported. */
5446         if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5447             is_ntfs_stream_smb_fname(smb_fname_new)) {
5448                 return NT_STATUS_INVALID_PARAMETER;
5449         }
5450
5451         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5452                   smb_fname_old->base_name, smb_fname_new->base_name));
5453
5454         if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5455                          smb_fname_new->base_name) != 0) {
5456                 status = map_nt_error_from_unix(errno);
5457                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5458                          nt_errstr(status), smb_fname_old->base_name,
5459                          smb_fname_new->base_name));
5460         }
5461         return status;
5462 }
5463
5464 /****************************************************************************
5465  Deal with setting the time from any of the setfilepathinfo functions.
5466  NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5467  calling this function.
5468 ****************************************************************************/
5469
5470 NTSTATUS smb_set_file_time(connection_struct *conn,
5471                            files_struct *fsp,
5472                            const struct smb_filename *smb_fname,
5473                            struct smb_file_time *ft,
5474                            bool setting_write_time)
5475 {
5476         struct smb_filename smb_fname_base;
5477         uint32 action =
5478                 FILE_NOTIFY_CHANGE_LAST_ACCESS
5479                 |FILE_NOTIFY_CHANGE_LAST_WRITE
5480                 |FILE_NOTIFY_CHANGE_CREATION;
5481
5482         if (!VALID_STAT(smb_fname->st)) {
5483                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5484         }
5485
5486         /* get some defaults (no modifications) if any info is zero or -1. */
5487         if (null_timespec(ft->create_time)) {
5488                 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5489         }
5490
5491         if (null_timespec(ft->atime)) {
5492                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5493         }
5494
5495         if (null_timespec(ft->mtime)) {
5496                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5497         }
5498
5499         if (!setting_write_time) {
5500                 /* ft->mtime comes from change time, not write time. */
5501                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5502         }
5503
5504         /* Ensure the resolution is the correct for
5505          * what we can store on this filesystem. */
5506
5507         round_timespec(conn->ts_res, &ft->create_time);
5508         round_timespec(conn->ts_res, &ft->ctime);
5509         round_timespec(conn->ts_res, &ft->atime);
5510         round_timespec(conn->ts_res, &ft->mtime);
5511
5512         DEBUG(5,("smb_set_filetime: actime: %s\n ",
5513                 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5514         DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5515                 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5516         DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5517                 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5518         DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5519                 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5520
5521         if (setting_write_time) {
5522                 /*
5523                  * This was a Windows setfileinfo on an open file.
5524                  * NT does this a lot. We also need to 
5525                  * set the time here, as it can be read by 
5526                  * FindFirst/FindNext and with the patch for bug #2045
5527                  * in smbd/fileio.c it ensures that this timestamp is
5528                  * kept sticky even after a write. We save the request
5529                  * away and will set it on file close and after a write. JRA.
5530                  */
5531
5532                 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5533                           time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5534
5535                 if (fsp != NULL) {
5536                         if (fsp->base_fsp) {
5537                                 set_sticky_write_time_fsp(fsp->base_fsp,
5538                                                           ft->mtime);
5539                         } else {
5540                                 set_sticky_write_time_fsp(fsp, ft->mtime);
5541                         }
5542                 } else {
5543                         set_sticky_write_time_path(
5544                                 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5545                                 ft->mtime);
5546                 }
5547         }
5548
5549         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5550
5551         /* Always call ntimes on the base, even if a stream was passed in. */
5552         smb_fname_base = *smb_fname;
5553         smb_fname_base.stream_name = NULL;
5554
5555         if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5556                 return map_nt_error_from_unix(errno);
5557         }
5558
5559         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5560                      smb_fname->base_name);
5561         return NT_STATUS_OK;
5562 }
5563
5564 /****************************************************************************
5565  Deal with setting the dosmode from any of the setfilepathinfo functions.
5566  NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5567  done before calling this function.
5568 ****************************************************************************/
5569
5570 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5571                                      const struct smb_filename *smb_fname,
5572                                      uint32 dosmode)
5573 {
5574         struct smb_filename *smb_fname_base = NULL;
5575         NTSTATUS status;
5576
5577         if (!VALID_STAT(smb_fname->st)) {
5578                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5579         }
5580
5581         /* Always operate on the base_name, even if a stream was passed in. */
5582         status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5583                                             NULL, &smb_fname->st,
5584                                             &smb_fname_base);
5585         if (!NT_STATUS_IS_OK(status)) {
5586                 return status;
5587         }
5588
5589         if (dosmode) {
5590                 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5591                         dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5592                 } else {
5593                         dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5594                 }
5595         }
5596
5597         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5598
5599         /* check the mode isn't different, before changing it */
5600         if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5601                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5602                           "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5603                           (unsigned int)dosmode));
5604
5605                 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5606                                     false)) {
5607                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5608                                  "%s failed (%s)\n",
5609                                  smb_fname_str_dbg(smb_fname_base),
5610                                  strerror(errno)));
5611                         status = map_nt_error_from_unix(errno);
5612                         goto out;
5613                 }
5614         }
5615         status = NT_STATUS_OK;
5616  out:
5617         TALLOC_FREE(smb_fname_base);
5618         return status;
5619 }
5620
5621 /****************************************************************************
5622  Deal with setting the size from any of the setfilepathinfo functions.
5623 ****************************************************************************/
5624
5625 static NTSTATUS smb_set_file_size(connection_struct *conn,
5626                                   struct smb_request *req,
5627                                   files_struct *fsp,
5628                                   const struct smb_filename *smb_fname,
5629                                   const SMB_STRUCT_STAT *psbuf,
5630                                   SMB_OFF_T size,
5631                                   bool fail_after_createfile)
5632 {
5633         NTSTATUS status = NT_STATUS_OK;
5634         struct smb_filename *smb_fname_tmp = NULL;
5635         files_struct *new_fsp = NULL;
5636
5637         if (!VALID_STAT(*psbuf)) {
5638                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5639         }
5640
5641         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5642
5643         if (size == get_file_size_stat(psbuf)) {
5644                 return NT_STATUS_OK;
5645         }
5646
5647         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5648                   smb_fname_str_dbg(smb_fname), (double)size));
5649
5650         if (fsp && fsp->fh->fd != -1) {
5651                 /* Handle based call. */
5652                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5653                         return NT_STATUS_ACCESS_DENIED;
5654                 }
5655
5656                 if (vfs_set_filelen(fsp, size) == -1) {
5657                         return map_nt_error_from_unix(errno);
5658                 }
5659                 trigger_write_time_update_immediate(fsp);
5660                 return NT_STATUS_OK;
5661         }
5662
5663         status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5664         if (!NT_STATUS_IS_OK(status)) {
5665                 return status;
5666         }
5667
5668         smb_fname_tmp->st = *psbuf;
5669
5670         status = SMB_VFS_CREATE_FILE(
5671                 conn,                                   /* conn */
5672                 req,                                    /* req */
5673                 0,                                      /* root_dir_fid */
5674                 smb_fname_tmp,                          /* fname */
5675                 FILE_WRITE_DATA,                        /* access_mask */
5676                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5677                     FILE_SHARE_DELETE),
5678                 FILE_OPEN,                              /* create_disposition*/
5679                 0,                                      /* create_options */
5680                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
5681                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
5682                 0,                                      /* allocation_size */
5683                 0,                                      /* private_flags */
5684                 NULL,                                   /* sd */
5685                 NULL,                                   /* ea_list */
5686                 &new_fsp,                               /* result */
5687                 NULL);                                  /* pinfo */
5688
5689         TALLOC_FREE(smb_fname_tmp);
5690
5691         if (!NT_STATUS_IS_OK(status)) {
5692                 /* NB. We check for open_was_deferred in the caller. */
5693                 return status;
5694         }
5695
5696         /* See RAW-SFILEINFO-END-OF-FILE */
5697         if (fail_after_createfile) {
5698                 close_file(req, new_fsp,NORMAL_CLOSE);
5699                 return NT_STATUS_INVALID_LEVEL;
5700         }
5701
5702         if (vfs_set_filelen(new_fsp, size) == -1) {
5703                 status = map_nt_error_from_unix(errno);
5704                 close_file(req, new_fsp,NORMAL_CLOSE);
5705                 return status;
5706         }
5707
5708         trigger_write_time_update_immediate(new_fsp);
5709         close_file(req, new_fsp,NORMAL_CLOSE);
5710         return NT_STATUS_OK;
5711 }
5712
5713 /****************************************************************************
5714  Deal with SMB_INFO_SET_EA.
5715 ****************************************************************************/
5716
5717 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5718                                 const char *pdata,
5719                                 int total_data,
5720                                 files_struct *fsp,
5721                                 const struct smb_filename *smb_fname)
5722 {
5723         struct ea_list *ea_list = NULL;
5724         TALLOC_CTX *ctx = NULL;
5725         NTSTATUS status = NT_STATUS_OK;
5726
5727         if (total_data < 10) {
5728
5729                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5730                    length. They seem to have no effect. Bug #3212. JRA */
5731
5732                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5733                         /* We're done. We only get EA info in this call. */
5734                         return NT_STATUS_OK;
5735                 }
5736
5737                 return NT_STATUS_INVALID_PARAMETER;
5738         }
5739
5740         if (IVAL(pdata,0) > total_data) {
5741                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5742                         IVAL(pdata,0), (unsigned int)total_data));
5743                 return NT_STATUS_INVALID_PARAMETER;
5744         }
5745
5746         ctx = talloc_tos();
5747         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5748         if (!ea_list) {
5749                 return NT_STATUS_INVALID_PARAMETER;
5750         }
5751
5752         status = set_ea(conn, fsp, smb_fname, ea_list);
5753
5754         return status;
5755 }
5756
5757 /****************************************************************************
5758  Deal with SMB_FILE_FULL_EA_INFORMATION set.
5759 ****************************************************************************/
5760
5761 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5762                                 const char *pdata,
5763                                 int total_data,
5764                                 files_struct *fsp)
5765 {
5766         struct ea_list *ea_list = NULL;
5767         NTSTATUS status;
5768
5769         if (!fsp) {
5770                 return NT_STATUS_INVALID_HANDLE;
5771         }
5772
5773         if (!lp_ea_support(SNUM(conn))) {
5774                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5775                         "EA's not supported.\n",
5776                         (unsigned int)total_data));
5777                 return NT_STATUS_EAS_NOT_SUPPORTED;
5778         }
5779
5780         if (total_data < 10) {
5781                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5782                         "too small.\n",
5783                         (unsigned int)total_data));
5784                 return NT_STATUS_INVALID_PARAMETER;
5785         }
5786
5787         ea_list = read_nttrans_ea_list(talloc_tos(),
5788                                 pdata,
5789                                 total_data);
5790
5791         if (!ea_list) {
5792                 return NT_STATUS_INVALID_PARAMETER;
5793         }
5794
5795         status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5796
5797         DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5798                 smb_fname_str_dbg(fsp->fsp_name),
5799                 nt_errstr(status) ));
5800
5801         return status;
5802 }
5803
5804
5805 /****************************************************************************
5806  Deal with SMB_SET_FILE_DISPOSITION_INFO.
5807 ****************************************************************************/
5808
5809 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5810                                 const char *pdata,
5811                                 int total_data,
5812                                 files_struct *fsp,
5813                                 struct smb_filename *smb_fname)
5814 {
5815         NTSTATUS status = NT_STATUS_OK;
5816         bool delete_on_close;
5817         uint32 dosmode = 0;
5818
5819         if (total_data < 1) {
5820                 return NT_STATUS_INVALID_PARAMETER;
5821         }
5822
5823         if (fsp == NULL) {
5824                 return NT_STATUS_INVALID_HANDLE;
5825         }
5826
5827         delete_on_close = (CVAL(pdata,0) ? True : False);
5828         dosmode = dos_mode(conn, smb_fname);
5829
5830         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5831                 "delete_on_close = %u\n",
5832                 smb_fname_str_dbg(smb_fname),
5833                 (unsigned int)dosmode,
5834                 (unsigned int)delete_on_close ));
5835
5836         if (delete_on_close) {
5837                 status = can_set_delete_on_close(fsp, dosmode);
5838                 if (!NT_STATUS_IS_OK(status)) {
5839                         return status;
5840                 }
5841         }
5842
5843         /* The set is across all open files on this dev/inode pair. */
5844         if (!set_delete_on_close(fsp, delete_on_close,
5845                                  conn->session_info->unix_token)) {
5846                 return NT_STATUS_ACCESS_DENIED;
5847         }
5848         return NT_STATUS_OK;
5849 }
5850
5851 /****************************************************************************
5852  Deal with SMB_FILE_POSITION_INFORMATION.
5853 ****************************************************************************/
5854
5855 static NTSTATUS smb_file_position_information(connection_struct *conn,
5856                                 const char *pdata,
5857                                 int total_data,
5858                                 files_struct *fsp)
5859 {
5860         uint64_t position_information;
5861
5862         if (total_data < 8) {
5863                 return NT_STATUS_INVALID_PARAMETER;
5864         }
5865
5866         if (fsp == NULL) {
5867                 /* Ignore on pathname based set. */
5868                 return NT_STATUS_OK;
5869         }
5870
5871         position_information = (uint64_t)IVAL(pdata,0);
5872 #ifdef LARGE_SMB_OFF_T
5873         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5874 #else /* LARGE_SMB_OFF_T */
5875         if (IVAL(pdata,4) != 0) {
5876                 /* more than 32 bits? */
5877                 return NT_STATUS_INVALID_PARAMETER;
5878         }
5879 #endif /* LARGE_SMB_OFF_T */
5880
5881         DEBUG(10,("smb_file_position_information: Set file position "
5882                   "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5883                   (double)position_information));
5884         fsp->fh->position_information = position_information;
5885         return NT_STATUS_OK;
5886 }
5887
5888 /****************************************************************************
5889  Deal with SMB_FILE_MODE_INFORMATION.
5890 ****************************************************************************/
5891
5892 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5893                                 const char *pdata,
5894                                 int total_data)
5895 {
5896         uint32 mode;
5897
5898         if (total_data < 4) {
5899                 return NT_STATUS_INVALID_PARAMETER;
5900         }
5901         mode = IVAL(pdata,0);
5902         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5903                 return NT_STATUS_INVALID_PARAMETER;
5904         }
5905         return NT_STATUS_OK;
5906 }
5907
5908 /****************************************************************************
5909  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5910 ****************************************************************************/
5911
5912 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5913                                        struct smb_request *req,
5914                                        const char *pdata,
5915                                        int total_data,
5916                                        const struct smb_filename *smb_fname)
5917 {
5918         char *link_target = NULL;
5919         const char *newname = smb_fname->base_name;
5920         TALLOC_CTX *ctx = talloc_tos();
5921
5922         /* Set a symbolic link. */
5923         /* Don't allow this if follow links is false. */
5924
5925         if (total_data == 0) {
5926                 return NT_STATUS_INVALID_PARAMETER;
5927         }
5928
5929         if (!lp_symlinks(SNUM(conn))) {
5930                 return NT_STATUS_ACCESS_DENIED;
5931         }
5932
5933         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5934                     total_data, STR_TERMINATE);
5935
5936         if (!link_target) {
5937                 return NT_STATUS_INVALID_PARAMETER;
5938         }
5939
5940         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5941                         newname, link_target ));
5942
5943         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5944                 return map_nt_error_from_unix(errno);
5945         }
5946
5947         return NT_STATUS_OK;
5948 }
5949
5950 /****************************************************************************
5951  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5952 ****************************************************************************/
5953
5954 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5955                                         struct smb_request *req,
5956                                         const char *pdata, int total_data,
5957                                         struct smb_filename *smb_fname_new)
5958 {
5959         char *oldname = NULL;
5960         struct smb_filename *smb_fname_old = NULL;
5961         TALLOC_CTX *ctx = talloc_tos();
5962         NTSTATUS status = NT_STATUS_OK;
5963
5964         /* Set a hard link. */
5965         if (total_data == 0) {
5966                 return NT_STATUS_INVALID_PARAMETER;
5967         }
5968
5969         srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5970                         total_data, STR_TERMINATE, &status);
5971         if (!NT_STATUS_IS_OK(status)) {
5972                 return status;
5973         }
5974
5975         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5976                 smb_fname_str_dbg(smb_fname_new), oldname));
5977
5978         status = filename_convert(ctx,
5979                                 conn,
5980                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
5981                                 oldname,
5982                                 0,
5983                                 NULL,
5984                                 &smb_fname_old);
5985         if (!NT_STATUS_IS_OK(status)) {
5986                 return status;
5987         }
5988
5989         return hardlink_internals(ctx, conn, req, false,
5990                         smb_fname_old, smb_fname_new);
5991 }
5992
5993 /****************************************************************************
5994  Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5995 ****************************************************************************/
5996
5997 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5998                                             struct smb_request *req,
5999                                             const char *pdata,
6000                                             int total_data,
6001                                             files_struct *fsp,
6002                                             struct smb_filename *smb_fname_src)
6003 {
6004         bool overwrite;
6005         uint32_t len;
6006         char *newname = NULL;
6007         struct smb_filename *smb_fname_dst = NULL;
6008         NTSTATUS status = NT_STATUS_OK;
6009         TALLOC_CTX *ctx = talloc_tos();
6010
6011         if (!fsp) {
6012                 return NT_STATUS_INVALID_HANDLE;
6013         }
6014
6015         if (total_data < 20) {
6016                 return NT_STATUS_INVALID_PARAMETER;
6017         }
6018
6019         overwrite = (CVAL(pdata,0) ? True : False);
6020         len = IVAL(pdata,16);
6021
6022         if (len > (total_data - 20) || (len == 0)) {
6023                 return NT_STATUS_INVALID_PARAMETER;
6024         }
6025
6026         srvstr_get_path(ctx, pdata, req->flags2, &newname,
6027                                 &pdata[20], len, STR_TERMINATE,
6028                                 &status);
6029         if (!NT_STATUS_IS_OK(status)) {
6030                 return status;
6031         }
6032
6033         DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6034                                 newname));
6035
6036         status = filename_convert(ctx,
6037                                 conn,
6038                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
6039                                 newname,
6040                                 UCF_SAVE_LCOMP,
6041                                 NULL,
6042                                 &smb_fname_dst);
6043         if (!NT_STATUS_IS_OK(status)) {
6044                 return status;
6045         }
6046
6047         if (fsp->base_fsp) {
6048                 /* newname must be a stream name. */
6049                 if (newname[0] != ':') {
6050                         return NT_STATUS_NOT_SUPPORTED;
6051                 }
6052
6053                 /* Create an smb_fname to call rename_internals_fsp() with. */
6054                 status = create_synthetic_smb_fname(talloc_tos(),
6055                     fsp->base_fsp->fsp_name->base_name, newname, NULL,
6056                     &smb_fname_dst);
6057                 if (!NT_STATUS_IS_OK(status)) {
6058                         goto out;
6059                 }
6060
6061                 /*
6062                  * Set the original last component, since
6063                  * rename_internals_fsp() requires it.
6064                  */
6065                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6066                                                               newname);
6067                 if (smb_fname_dst->original_lcomp == NULL) {
6068                         status = NT_STATUS_NO_MEMORY;
6069                         goto out;
6070                 }
6071
6072         }
6073
6074         DEBUG(10,("smb2_file_rename_information: "
6075                   "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6076                   fsp->fnum, fsp_str_dbg(fsp),
6077                   smb_fname_str_dbg(smb_fname_dst)));
6078         status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6079                                 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6080                                 overwrite);
6081
6082  out:
6083         TALLOC_FREE(smb_fname_dst);
6084         return status;
6085 }
6086
6087 static NTSTATUS smb_file_link_information(connection_struct *conn,
6088                                             struct smb_request *req,
6089                                             const char *pdata,
6090                                             int total_data,
6091                                             files_struct *fsp,
6092                                             struct smb_filename *smb_fname_src)
6093 {
6094         bool overwrite;
6095         uint32_t len;
6096         char *newname = NULL;
6097         struct smb_filename *smb_fname_dst = NULL;
6098         NTSTATUS status = NT_STATUS_OK;
6099         TALLOC_CTX *ctx = talloc_tos();
6100
6101         if (!fsp) {
6102                 return NT_STATUS_INVALID_HANDLE;
6103         }
6104
6105         if (total_data < 20) {
6106                 return NT_STATUS_INVALID_PARAMETER;
6107         }
6108
6109         overwrite = (CVAL(pdata,0) ? true : false);
6110         len = IVAL(pdata,16);
6111
6112         if (len > (total_data - 20) || (len == 0)) {
6113                 return NT_STATUS_INVALID_PARAMETER;
6114         }
6115
6116         srvstr_get_path(ctx, pdata, req->flags2, &newname,
6117                                 &pdata[20], len, STR_TERMINATE,
6118                                 &status);
6119         if (!NT_STATUS_IS_OK(status)) {
6120                 return status;
6121         }
6122
6123         DEBUG(10,("smb_file_link_information: got name |%s|\n",
6124                                 newname));
6125
6126         status = filename_convert(ctx,
6127                                 conn,
6128                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
6129                                 newname,
6130                                 UCF_SAVE_LCOMP,
6131                                 NULL,
6132                                 &smb_fname_dst);
6133         if (!NT_STATUS_IS_OK(status)) {
6134                 return status;
6135         }
6136
6137         if (fsp->base_fsp) {
6138                 /* No stream names. */
6139                 return NT_STATUS_NOT_SUPPORTED;
6140         }
6141
6142         DEBUG(10,("smb_file_link_information: "
6143                   "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6144                   fsp->fnum, fsp_str_dbg(fsp),
6145                   smb_fname_str_dbg(smb_fname_dst)));
6146         status = hardlink_internals(ctx,
6147                                 conn,
6148                                 req,
6149                                 overwrite,
6150                                 fsp->fsp_name,
6151                                 smb_fname_dst);
6152
6153         TALLOC_FREE(smb_fname_dst);
6154         return status;
6155 }
6156
6157 /****************************************************************************
6158  Deal with SMB_FILE_RENAME_INFORMATION.
6159 ****************************************************************************/
6160
6161 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6162                                             struct smb_request *req,
6163                                             const char *pdata,
6164                                             int total_data,
6165                                             files_struct *fsp,
6166                                             struct smb_filename *smb_fname_src)
6167 {
6168         bool overwrite;
6169         uint32 root_fid;
6170         uint32 len;
6171         char *newname = NULL;
6172         struct smb_filename *smb_fname_dst = NULL;
6173         bool dest_has_wcard = False;
6174         NTSTATUS status = NT_STATUS_OK;
6175         char *p;
6176         TALLOC_CTX *ctx = talloc_tos();
6177
6178         if (total_data < 13) {
6179                 return NT_STATUS_INVALID_PARAMETER;
6180         }
6181
6182         overwrite = (CVAL(pdata,0) ? True : False);
6183         root_fid = IVAL(pdata,4);
6184         len = IVAL(pdata,8);
6185
6186         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6187                 return NT_STATUS_INVALID_PARAMETER;
6188         }
6189
6190         srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6191                               len, 0, &status,
6192                               &dest_has_wcard);
6193         if (!NT_STATUS_IS_OK(status)) {
6194                 return status;
6195         }
6196
6197         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6198                                 newname));
6199
6200         status = resolve_dfspath_wcard(ctx, conn,
6201                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6202                                        newname,
6203                                        true,
6204                                        &newname,
6205                                        &dest_has_wcard);
6206         if (!NT_STATUS_IS_OK(status)) {
6207                 return status;
6208         }
6209
6210         /* Check the new name has no '/' characters. */
6211         if (strchr_m(newname, '/')) {
6212                 return NT_STATUS_NOT_SUPPORTED;
6213         }
6214
6215         if (fsp && fsp->base_fsp) {
6216                 /* newname must be a stream name. */
6217                 if (newname[0] != ':') {
6218                         return NT_STATUS_NOT_SUPPORTED;
6219                 }
6220
6221                 /* Create an smb_fname to call rename_internals_fsp() with. */
6222                 status = create_synthetic_smb_fname(talloc_tos(),
6223                     fsp->base_fsp->fsp_name->base_name, newname, NULL,
6224                     &smb_fname_dst);
6225                 if (!NT_STATUS_IS_OK(status)) {
6226                         goto out;
6227                 }
6228
6229                 /*
6230                  * Set the original last component, since
6231                  * rename_internals_fsp() requires it.
6232                  */
6233                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6234                                                               newname);
6235                 if (smb_fname_dst->original_lcomp == NULL) {
6236                         status = NT_STATUS_NO_MEMORY;
6237                         goto out;
6238                 }
6239
6240         } else {
6241                 /*
6242                  * Build up an smb_fname_dst based on the filename passed in.
6243                  * We basically just strip off the last component, and put on
6244                  * the newname instead.
6245                  */
6246                 char *base_name = NULL;
6247
6248                 /* newname must *not* be a stream name. */
6249                 if (newname[0] == ':') {
6250                         return NT_STATUS_NOT_SUPPORTED;
6251                 }
6252
6253                 /*
6254                  * Strip off the last component (filename) of the path passed
6255                  * in.
6256                  */
6257                 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6258                 if (!base_name) {
6259                         return NT_STATUS_NO_MEMORY;
6260                 }
6261                 p = strrchr_m(base_name, '/');
6262                 if (p) {
6263                         p[1] = '\0';
6264                 } else {
6265                         base_name = talloc_strdup(ctx, "");
6266                         if (!base_name) {
6267                                 return NT_STATUS_NO_MEMORY;
6268                         }
6269                 }
6270                 /* Append the new name. */
6271                 base_name = talloc_asprintf_append(base_name,
6272                                 "%s",
6273                                 newname);
6274                 if (!base_name) {
6275                         return NT_STATUS_NO_MEMORY;
6276                 }
6277
6278                 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6279                                       (UCF_SAVE_LCOMP |
6280                                           (dest_has_wcard ?
6281                                               UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6282                                               0)));
6283
6284                 /* If an error we expect this to be
6285                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6286
6287                 if (!NT_STATUS_IS_OK(status)) {
6288                         if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6289                                             status)) {
6290                                 goto out;
6291                         }
6292                         /* Create an smb_fname to call rename_internals_fsp() */
6293                         status = create_synthetic_smb_fname(ctx,
6294                                                             base_name, NULL,
6295                                                             NULL,
6296                                                             &smb_fname_dst);
6297                         if (!NT_STATUS_IS_OK(status)) {
6298                                 goto out;
6299                         }
6300                 }
6301         }
6302
6303         if (fsp) {
6304                 DEBUG(10,("smb_file_rename_information: "
6305                           "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6306                           fsp->fnum, fsp_str_dbg(fsp),
6307                           smb_fname_str_dbg(smb_fname_dst)));
6308                 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6309                                               overwrite);
6310         } else {
6311                 DEBUG(10,("smb_file_rename_information: "
6312                           "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6313                           smb_fname_str_dbg(smb_fname_src),
6314                           smb_fname_str_dbg(smb_fname_dst)));
6315                 status = rename_internals(ctx, conn, req, smb_fname_src,
6316                                           smb_fname_dst, 0, overwrite, false,
6317                                           dest_has_wcard,
6318                                           FILE_WRITE_ATTRIBUTES);
6319         }
6320  out:
6321         TALLOC_FREE(smb_fname_dst);
6322         return status;
6323 }
6324
6325 /****************************************************************************
6326  Deal with SMB_SET_POSIX_ACL.
6327 ****************************************************************************/
6328
6329 #if defined(HAVE_POSIX_ACLS)
6330 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6331                                 const char *pdata,
6332                                 int total_data,
6333                                 files_struct *fsp,
6334                                 const struct smb_filename *smb_fname)
6335 {
6336         uint16 posix_acl_version;
6337         uint16 num_file_acls;
6338         uint16 num_def_acls;
6339         bool valid_file_acls = True;
6340         bool valid_def_acls = True;
6341
6342         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6343                 return NT_STATUS_INVALID_PARAMETER;
6344         }
6345         posix_acl_version = SVAL(pdata,0);
6346         num_file_acls = SVAL(pdata,2);
6347         num_def_acls = SVAL(pdata,4);
6348
6349         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6350                 valid_file_acls = False;
6351                 num_file_acls = 0;
6352         }
6353
6354         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6355                 valid_def_acls = False;
6356                 num_def_acls = 0;
6357         }
6358
6359         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6360                 return NT_STATUS_INVALID_PARAMETER;
6361         }
6362
6363         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6364                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6365                 return NT_STATUS_INVALID_PARAMETER;
6366         }
6367
6368         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6369                 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6370                 (unsigned int)num_file_acls,
6371                 (unsigned int)num_def_acls));
6372
6373         if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6374                 smb_fname->base_name, num_file_acls,
6375                 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6376                 return map_nt_error_from_unix(errno);
6377         }
6378
6379         if (valid_def_acls && !set_unix_posix_default_acl(conn,
6380                 smb_fname->base_name, &smb_fname->st, num_def_acls,
6381                 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6382                 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6383                 return map_nt_error_from_unix(errno);
6384         }
6385         return NT_STATUS_OK;
6386 }
6387 #endif
6388
6389 /****************************************************************************
6390  Deal with SMB_SET_POSIX_LOCK.
6391 ****************************************************************************/
6392
6393 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6394                                 struct smb_request *req,
6395                                 const char *pdata,
6396                                 int total_data,
6397                                 files_struct *fsp)
6398 {
6399         uint64_t count;
6400         uint64_t offset;
6401         uint64_t smblctx;
6402         bool blocking_lock = False;
6403         enum brl_type lock_type;
6404
6405         NTSTATUS status = NT_STATUS_OK;
6406
6407         if (fsp == NULL || fsp->fh->fd == -1) {
6408                 return NT_STATUS_INVALID_HANDLE;
6409         }
6410
6411         if (total_data != POSIX_LOCK_DATA_SIZE) {
6412                 return NT_STATUS_INVALID_PARAMETER;
6413         }
6414
6415         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6416                 case POSIX_LOCK_TYPE_READ:
6417                         lock_type = READ_LOCK;
6418                         break;
6419                 case POSIX_LOCK_TYPE_WRITE:
6420                         /* Return the right POSIX-mappable error code for files opened read-only. */
6421                         if (!fsp->can_write) {
6422                                 return NT_STATUS_INVALID_HANDLE;
6423                         }
6424                         lock_type = WRITE_LOCK;
6425                         break;
6426                 case POSIX_LOCK_TYPE_UNLOCK:
6427                         lock_type = UNLOCK_LOCK;
6428                         break;
6429                 default:
6430                         return NT_STATUS_INVALID_PARAMETER;
6431         }
6432
6433         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6434                 blocking_lock = False;
6435         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6436                 blocking_lock = True;
6437         } else {
6438                 return NT_STATUS_INVALID_PARAMETER;
6439         }
6440
6441         if (!lp_blocking_locks(SNUM(conn))) { 
6442                 blocking_lock = False;
6443         }
6444
6445         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6446 #if defined(HAVE_LONGLONG)
6447         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6448                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6449         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6450                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6451 #else /* HAVE_LONGLONG */
6452         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6453         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6454 #endif /* HAVE_LONGLONG */
6455
6456         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6457                         "smblctx = %llu, count = %.0f, offset = %.0f\n",
6458                 fsp_str_dbg(fsp),
6459                 (unsigned int)lock_type,
6460                 (unsigned long long)smblctx,
6461                 (double)count,
6462                 (double)offset ));
6463
6464         if (lock_type == UNLOCK_LOCK) {
6465                 status = do_unlock(req->sconn->msg_ctx,
6466                                 fsp,
6467                                 smblctx,
6468                                 count,
6469                                 offset,
6470                                 POSIX_LOCK);
6471         } else {
6472                 uint64_t block_smblctx;
6473
6474                 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6475                                                         fsp,
6476                                                         smblctx,
6477                                                         count,
6478                                                         offset,
6479                                                         lock_type,
6480                                                         POSIX_LOCK,
6481                                                         blocking_lock,
6482                                                         &status,
6483                                                         &block_smblctx,
6484                                                         NULL);
6485
6486                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6487                         /*
6488                          * A blocking lock was requested. Package up
6489                          * this smb into a queued request and push it
6490                          * onto the blocking lock queue.
6491                          */
6492                         if(push_blocking_lock_request(br_lck,
6493                                                 req,
6494                                                 fsp,
6495                                                 -1, /* infinite timeout. */
6496                                                 0,
6497                                                 smblctx,
6498                                                 lock_type,
6499                                                 POSIX_LOCK,
6500                                                 offset,
6501                                                 count,
6502                                                 block_smblctx)) {
6503                                 TALLOC_FREE(br_lck);
6504                                 return status;
6505                         }
6506                 }
6507                 TALLOC_FREE(br_lck);
6508         }
6509
6510         return status;
6511 }
6512
6513 /****************************************************************************
6514  Deal with SMB_SET_FILE_BASIC_INFO.
6515 ****************************************************************************/
6516
6517 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6518                                         const char *pdata,
6519                                         int total_data,
6520                                         files_struct *fsp,
6521                                         const struct smb_filename *smb_fname)
6522 {
6523         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6524         struct smb_file_time ft;
6525         uint32 dosmode = 0;
6526         NTSTATUS status = NT_STATUS_OK;
6527
6528         ZERO_STRUCT(ft);
6529
6530         if (total_data < 36) {
6531                 return NT_STATUS_INVALID_PARAMETER;
6532         }
6533
6534         status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6535         if (!NT_STATUS_IS_OK(status)) {
6536                 return status;
6537         }
6538
6539         /* Set the attributes */
6540         dosmode = IVAL(pdata,32);
6541         status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6542         if (!NT_STATUS_IS_OK(status)) {
6543                 return status;
6544         }
6545
6546         /* create time */
6547         ft.create_time = interpret_long_date(pdata);
6548
6549         /* access time */
6550         ft.atime = interpret_long_date(pdata+8);
6551
6552         /* write time. */
6553         ft.mtime = interpret_long_date(pdata+16);
6554
6555         /* change time. */
6556         ft.ctime = interpret_long_date(pdata+24);
6557
6558         DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6559                    smb_fname_str_dbg(smb_fname)));
6560
6561         return smb_set_file_time(conn, fsp, smb_fname, &ft,
6562                                  true);
6563 }
6564
6565 /****************************************************************************
6566  Deal with SMB_INFO_STANDARD.
6567 ****************************************************************************/
6568
6569 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6570                                         const char *pdata,
6571                                         int total_data,
6572                                         files_struct *fsp,
6573                                         const struct smb_filename *smb_fname)
6574 {
6575         NTSTATUS status;
6576         struct smb_file_time ft;
6577
6578         ZERO_STRUCT(ft);
6579
6580         if (total_data < 12) {
6581                 return NT_STATUS_INVALID_PARAMETER;
6582         }
6583
6584         /* create time */
6585         ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6586         /* access time */
6587         ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6588         /* write time */
6589         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6590
6591         DEBUG(10,("smb_set_info_standard: file %s\n",
6592                 smb_fname_str_dbg(smb_fname)));
6593
6594         status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6595         if (!NT_STATUS_IS_OK(status)) {
6596                 return status;
6597         }
6598
6599         return smb_set_file_time(conn,
6600                                 fsp,
6601                                 smb_fname,
6602                                 &ft,
6603                                 true);
6604 }
6605
6606 /****************************************************************************
6607  Deal with SMB_SET_FILE_ALLOCATION_INFO.
6608 ****************************************************************************/
6609
6610 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6611                                              struct smb_request *req,
6612                                         const char *pdata,
6613                                         int total_data,
6614                                         files_struct *fsp,
6615                                         struct smb_filename *smb_fname)
6616 {
6617         uint64_t allocation_size = 0;
6618         NTSTATUS status = NT_STATUS_OK;
6619         files_struct *new_fsp = NULL;
6620
6621         if (!VALID_STAT(smb_fname->st)) {
6622                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6623         }
6624
6625         if (total_data < 8) {
6626                 return NT_STATUS_INVALID_PARAMETER;
6627         }
6628
6629         allocation_size = (uint64_t)IVAL(pdata,0);
6630 #ifdef LARGE_SMB_OFF_T
6631         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6632 #else /* LARGE_SMB_OFF_T */
6633         if (IVAL(pdata,4) != 0) {
6634                 /* more than 32 bits? */
6635                 return NT_STATUS_INVALID_PARAMETER;
6636         }
6637 #endif /* LARGE_SMB_OFF_T */
6638
6639         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6640                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6641                   (double)allocation_size));
6642
6643         if (allocation_size) {
6644                 allocation_size = smb_roundup(conn, allocation_size);
6645         }
6646
6647         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6648                   "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6649                   (double)allocation_size));
6650
6651         if (fsp && fsp->fh->fd != -1) {
6652                 /* Open file handle. */
6653                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6654                         return NT_STATUS_ACCESS_DENIED;
6655                 }
6656
6657                 /* Only change if needed. */
6658                 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6659                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6660                                 return map_nt_error_from_unix(errno);
6661                         }
6662                 }
6663                 /* But always update the time. */
6664                 /*
6665                  * This is equivalent to a write. Ensure it's seen immediately
6666                  * if there are no pending writes.
6667                  */
6668                 trigger_write_time_update_immediate(fsp);
6669                 return NT_STATUS_OK;
6670         }
6671
6672         /* Pathname or stat or directory file. */
6673         status = SMB_VFS_CREATE_FILE(
6674                 conn,                                   /* conn */
6675                 req,                                    /* req */
6676                 0,                                      /* root_dir_fid */
6677                 smb_fname,                              /* fname */
6678                 FILE_WRITE_DATA,                        /* access_mask */
6679                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6680                     FILE_SHARE_DELETE),
6681                 FILE_OPEN,                              /* create_disposition*/
6682                 0,                                      /* create_options */
6683                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6684                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
6685                 0,                                      /* allocation_size */
6686                 0,                                      /* private_flags */
6687                 NULL,                                   /* sd */
6688                 NULL,                                   /* ea_list */
6689                 &new_fsp,                               /* result */
6690                 NULL);                                  /* pinfo */
6691
6692         if (!NT_STATUS_IS_OK(status)) {
6693                 /* NB. We check for open_was_deferred in the caller. */
6694                 return status;
6695         }
6696
6697         /* Only change if needed. */
6698         if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6699                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6700                         status = map_nt_error_from_unix(errno);
6701                         close_file(req, new_fsp, NORMAL_CLOSE);
6702                         return status;
6703                 }
6704         }
6705
6706         /* Changing the allocation size should set the last mod time. */
6707         /*
6708          * This is equivalent to a write. Ensure it's seen immediately
6709          * if there are no pending writes.
6710          */
6711         trigger_write_time_update_immediate(new_fsp);
6712
6713         close_file(req, new_fsp, NORMAL_CLOSE);
6714         return NT_STATUS_OK;
6715 }
6716
6717 /****************************************************************************
6718  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6719 ****************************************************************************/
6720
6721 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6722                                               struct smb_request *req,
6723                                         const char *pdata,
6724                                         int total_data,
6725                                         files_struct *fsp,
6726                                         const struct smb_filename *smb_fname,
6727                                         bool fail_after_createfile)
6728 {
6729         SMB_OFF_T size;
6730
6731         if (total_data < 8) {
6732                 return NT_STATUS_INVALID_PARAMETER;
6733         }
6734
6735         size = IVAL(pdata,0);
6736 #ifdef LARGE_SMB_OFF_T
6737         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6738 #else /* LARGE_SMB_OFF_T */
6739         if (IVAL(pdata,4) != 0) {
6740                 /* more than 32 bits? */
6741                 return NT_STATUS_INVALID_PARAMETER;
6742         }
6743 #endif /* LARGE_SMB_OFF_T */
6744         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6745                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6746                   (double)size));
6747
6748         return smb_set_file_size(conn, req,
6749                                 fsp,
6750                                 smb_fname,
6751                                 &smb_fname->st,
6752                                 size,
6753                                 fail_after_createfile);
6754 }
6755
6756 /****************************************************************************
6757  Allow a UNIX info mknod.
6758 ****************************************************************************/
6759
6760 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6761                                         const char *pdata,
6762                                         int total_data,
6763                                         const struct smb_filename *smb_fname)
6764 {
6765         uint32 file_type = IVAL(pdata,56);
6766 #if defined(HAVE_MAKEDEV)
6767         uint32 dev_major = IVAL(pdata,60);
6768         uint32 dev_minor = IVAL(pdata,68);
6769 #endif
6770         SMB_DEV_T dev = (SMB_DEV_T)0;
6771         uint32 raw_unixmode = IVAL(pdata,84);
6772         NTSTATUS status;
6773         mode_t unixmode;
6774
6775         if (total_data < 100) {
6776                 return NT_STATUS_INVALID_PARAMETER;
6777         }
6778
6779         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6780                                       PERM_NEW_FILE, &unixmode);
6781         if (!NT_STATUS_IS_OK(status)) {
6782                 return status;
6783         }
6784
6785 #if defined(HAVE_MAKEDEV)
6786         dev = makedev(dev_major, dev_minor);
6787 #endif
6788
6789         switch (file_type) {
6790 #if defined(S_IFIFO)
6791                 case UNIX_TYPE_FIFO:
6792                         unixmode |= S_IFIFO;
6793                         break;
6794 #endif
6795 #if defined(S_IFSOCK)
6796                 case UNIX_TYPE_SOCKET:
6797                         unixmode |= S_IFSOCK;
6798                         break;
6799 #endif
6800 #if defined(S_IFCHR)
6801                 case UNIX_TYPE_CHARDEV:
6802                         unixmode |= S_IFCHR;
6803                         break;
6804 #endif
6805 #if defined(S_IFBLK)
6806                 case UNIX_TYPE_BLKDEV:
6807                         unixmode |= S_IFBLK;
6808                         break;
6809 #endif
6810                 default:
6811                         return NT_STATUS_INVALID_PARAMETER;
6812         }
6813
6814         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6815                   "%.0f mode 0%o for file %s\n", (double)dev,
6816                   (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6817
6818         /* Ok - do the mknod. */
6819         if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6820                 return map_nt_error_from_unix(errno);
6821         }
6822
6823         /* If any of the other "set" calls fail we
6824          * don't want to end up with a half-constructed mknod.
6825          */
6826
6827         if (lp_inherit_perms(SNUM(conn))) {
6828                 char *parent;
6829                 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6830                                     &parent, NULL)) {
6831                         return NT_STATUS_NO_MEMORY;
6832                 }
6833                 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6834                                          unixmode);
6835                 TALLOC_FREE(parent);
6836         }
6837
6838         return NT_STATUS_OK;
6839 }
6840
6841 /****************************************************************************
6842  Deal with SMB_SET_FILE_UNIX_BASIC.
6843 ****************************************************************************/
6844
6845 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6846                                         struct smb_request *req,
6847                                         const char *pdata,
6848                                         int total_data,
6849                                         files_struct *fsp,
6850                                         const struct smb_filename *smb_fname)
6851 {
6852         struct smb_file_time ft;
6853         uint32 raw_unixmode;
6854         mode_t unixmode;
6855         SMB_OFF_T size = 0;
6856         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6857         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6858         NTSTATUS status = NT_STATUS_OK;
6859         bool delete_on_fail = False;
6860         enum perm_type ptype;
6861         files_struct *all_fsps = NULL;
6862         bool modify_mtime = true;
6863         struct file_id id;
6864         struct smb_filename *smb_fname_tmp = NULL;
6865         SMB_STRUCT_STAT sbuf;
6866
6867         ZERO_STRUCT(ft);
6868
6869         if (total_data < 100) {
6870                 return NT_STATUS_INVALID_PARAMETER;
6871         }
6872
6873         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6874            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6875                 size=IVAL(pdata,0); /* first 8 Bytes are size */
6876 #ifdef LARGE_SMB_OFF_T
6877                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6878 #else /* LARGE_SMB_OFF_T */
6879                 if (IVAL(pdata,4) != 0) {
6880                         /* more than 32 bits? */
6881                         return NT_STATUS_INVALID_PARAMETER;
6882                 }
6883 #endif /* LARGE_SMB_OFF_T */
6884         }
6885
6886         ft.atime = interpret_long_date(pdata+24); /* access_time */
6887         ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6888         set_owner = (uid_t)IVAL(pdata,40);
6889         set_grp = (gid_t)IVAL(pdata,48);
6890         raw_unixmode = IVAL(pdata,84);
6891
6892         if (VALID_STAT(smb_fname->st)) {
6893                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6894                         ptype = PERM_EXISTING_DIR;
6895                 } else {
6896                         ptype = PERM_EXISTING_FILE;
6897                 }
6898         } else {
6899                 ptype = PERM_NEW_FILE;
6900         }
6901
6902         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6903                                       ptype, &unixmode);
6904         if (!NT_STATUS_IS_OK(status)) {
6905                 return status;
6906         }
6907
6908         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6909                   "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6910                   smb_fname_str_dbg(smb_fname), (double)size,
6911                   (unsigned int)set_owner, (unsigned int)set_grp,
6912                   (int)raw_unixmode));
6913
6914         sbuf = smb_fname->st;
6915
6916         if (!VALID_STAT(sbuf)) {
6917                 /*
6918                  * The only valid use of this is to create character and block
6919                  * devices, and named pipes. This is deprecated (IMHO) and 
6920                  * a new info level should be used for mknod. JRA.
6921                  */
6922
6923                 status = smb_unix_mknod(conn,
6924                                         pdata,
6925                                         total_data,
6926                                         smb_fname);
6927                 if (!NT_STATUS_IS_OK(status)) {
6928                         return status;
6929                 }
6930
6931                 status = copy_smb_filename(talloc_tos(), smb_fname,
6932                                            &smb_fname_tmp);
6933                 if (!NT_STATUS_IS_OK(status)) {
6934                         return status;
6935                 }
6936
6937                 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6938                         status = map_nt_error_from_unix(errno);
6939                         TALLOC_FREE(smb_fname_tmp);
6940                         SMB_VFS_UNLINK(conn, smb_fname);
6941                         return status;
6942                 }
6943
6944                 sbuf = smb_fname_tmp->st;
6945                 smb_fname = smb_fname_tmp;
6946
6947                 /* Ensure we don't try and change anything else. */
6948                 raw_unixmode = SMB_MODE_NO_CHANGE;
6949                 size = get_file_size_stat(&sbuf);
6950                 ft.atime = sbuf.st_ex_atime;
6951                 ft.mtime = sbuf.st_ex_mtime;
6952                 /* 
6953                  * We continue here as we might want to change the 
6954                  * owner uid/gid.
6955                  */
6956                 delete_on_fail = True;
6957         }
6958
6959 #if 1
6960         /* Horrible backwards compatibility hack as an old server bug
6961          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6962          * */
6963
6964         if (!size) {
6965                 size = get_file_size_stat(&sbuf);
6966         }
6967 #endif
6968
6969         /*
6970          * Deal with the UNIX specific mode set.
6971          */
6972
6973         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6974                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6975                           "setting mode 0%o for file %s\n",
6976                           (unsigned int)unixmode,
6977                           smb_fname_str_dbg(smb_fname)));
6978                 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6979                         return map_nt_error_from_unix(errno);
6980                 }
6981         }
6982
6983         /*
6984          * Deal with the UNIX specific uid set.
6985          */
6986
6987         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6988             (sbuf.st_ex_uid != set_owner)) {
6989                 int ret;
6990
6991                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6992                           "changing owner %u for path %s\n",
6993                           (unsigned int)set_owner,
6994                           smb_fname_str_dbg(smb_fname)));
6995
6996                 if (S_ISLNK(sbuf.st_ex_mode)) {
6997                         ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6998                                              set_owner, (gid_t)-1);
6999                 } else {
7000                         ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7001                                             set_owner, (gid_t)-1);
7002                 }
7003
7004                 if (ret != 0) {
7005                         status = map_nt_error_from_unix(errno);
7006                         if (delete_on_fail) {
7007                                 SMB_VFS_UNLINK(conn, smb_fname);
7008                         }
7009                         return status;
7010                 }
7011         }
7012
7013         /*
7014          * Deal with the UNIX specific gid set.
7015          */
7016
7017         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7018             (sbuf.st_ex_gid != set_grp)) {
7019                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7020                           "changing group %u for file %s\n",
7021                           (unsigned int)set_owner,
7022                           smb_fname_str_dbg(smb_fname)));
7023                 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7024                                   set_grp) != 0) {
7025                         status = map_nt_error_from_unix(errno);
7026                         if (delete_on_fail) {
7027                                 SMB_VFS_UNLINK(conn, smb_fname);
7028                         }
7029                         return status;
7030                 }
7031         }
7032
7033         /* Deal with any size changes. */
7034
7035         status = smb_set_file_size(conn, req,
7036                                    fsp,
7037                                    smb_fname,
7038                                    &sbuf,
7039                                    size,
7040                                    false);
7041         if (!NT_STATUS_IS_OK(status)) {
7042                 return status;
7043         }
7044
7045         /* Deal with any time changes. */
7046         if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7047                 /* No change, don't cancel anything. */
7048                 return status;
7049         }
7050
7051         id = vfs_file_id_from_sbuf(conn, &sbuf);
7052         for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7053                         all_fsps = file_find_di_next(all_fsps)) {
7054                 /*
7055                  * We're setting the time explicitly for UNIX.
7056                  * Cancel any pending changes over all handles.
7057                  */
7058                 all_fsps->update_write_time_on_close = false;
7059                 TALLOC_FREE(all_fsps->update_write_time_event);
7060         }
7061
7062         /*
7063          * Override the "setting_write_time"
7064          * parameter here as it almost does what
7065          * we need. Just remember if we modified
7066          * mtime and send the notify ourselves.
7067          */
7068         if (null_timespec(ft.mtime)) {
7069                 modify_mtime = false;
7070         }
7071
7072         status = smb_set_file_time(conn,
7073                                 fsp,
7074                                 smb_fname,
7075                                 &ft,
7076                                 false);
7077         if (modify_mtime) {
7078                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7079                         FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7080         }
7081         return status;
7082 }
7083
7084 /****************************************************************************
7085  Deal with SMB_SET_FILE_UNIX_INFO2.
7086 ****************************************************************************/
7087
7088 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7089                                         struct smb_request *req,
7090                                         const char *pdata,
7091                                         int total_data,
7092                                         files_struct *fsp,
7093                                         const struct smb_filename *smb_fname)
7094 {
7095         NTSTATUS status;
7096         uint32 smb_fflags;
7097         uint32 smb_fmask;
7098
7099         if (total_data < 116) {
7100                 return NT_STATUS_INVALID_PARAMETER;
7101         }
7102
7103         /* Start by setting all the fields that are common between UNIX_BASIC
7104          * and UNIX_INFO2.
7105          */
7106         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7107                                          fsp, smb_fname);
7108         if (!NT_STATUS_IS_OK(status)) {
7109                 return status;
7110         }
7111
7112         smb_fflags = IVAL(pdata, 108);
7113         smb_fmask = IVAL(pdata, 112);
7114
7115         /* NB: We should only attempt to alter the file flags if the client
7116          * sends a non-zero mask.
7117          */
7118         if (smb_fmask != 0) {
7119                 int stat_fflags = 0;
7120
7121                 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7122                                              smb_fmask, &stat_fflags)) {
7123                         /* Client asked to alter a flag we don't understand. */
7124                         return NT_STATUS_INVALID_PARAMETER;
7125                 }
7126
7127                 if (fsp && fsp->fh->fd != -1) {
7128                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
7129                         return NT_STATUS_NOT_SUPPORTED;
7130                 } else {
7131                         if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7132                                             stat_fflags) != 0) {
7133                                 return map_nt_error_from_unix(errno);
7134                         }
7135                 }
7136         }
7137
7138         /* XXX: need to add support for changing the create_time here. You
7139          * can do this for paths on Darwin with setattrlist(2). The right way
7140          * to hook this up is probably by extending the VFS utimes interface.
7141          */
7142
7143         return NT_STATUS_OK;
7144 }
7145
7146 /****************************************************************************
7147  Create a directory with POSIX semantics.
7148 ****************************************************************************/
7149
7150 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7151                                 struct smb_request *req,
7152                                 char **ppdata,
7153                                 int total_data,
7154                                 struct smb_filename *smb_fname,
7155                                 int *pdata_return_size)
7156 {
7157         NTSTATUS status = NT_STATUS_OK;
7158         uint32 raw_unixmode = 0;
7159         uint32 mod_unixmode = 0;
7160         mode_t unixmode = (mode_t)0;
7161         files_struct *fsp = NULL;
7162         uint16 info_level_return = 0;
7163         int info;
7164         char *pdata = *ppdata;
7165
7166         if (total_data < 18) {
7167                 return NT_STATUS_INVALID_PARAMETER;
7168         }
7169
7170         raw_unixmode = IVAL(pdata,8);
7171         /* Next 4 bytes are not yet defined. */
7172
7173         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7174                                       PERM_NEW_DIR, &unixmode);
7175         if (!NT_STATUS_IS_OK(status)) {
7176                 return status;
7177         }
7178
7179         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7180
7181         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7182                   smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7183
7184         status = SMB_VFS_CREATE_FILE(
7185                 conn,                                   /* conn */
7186                 req,                                    /* req */
7187                 0,                                      /* root_dir_fid */
7188                 smb_fname,                              /* fname */
7189                 FILE_READ_ATTRIBUTES,                   /* access_mask */
7190                 FILE_SHARE_NONE,                        /* share_access */
7191                 FILE_CREATE,                            /* create_disposition*/
7192                 FILE_DIRECTORY_FILE,                    /* create_options */
7193                 mod_unixmode,                           /* file_attributes */
7194                 0,                                      /* oplock_request */
7195                 0,                                      /* allocation_size */
7196                 0,                                      /* private_flags */
7197                 NULL,                                   /* sd */
7198                 NULL,                                   /* ea_list */
7199                 &fsp,                                   /* result */
7200                 &info);                                 /* pinfo */
7201
7202         if (NT_STATUS_IS_OK(status)) {
7203                 close_file(req, fsp, NORMAL_CLOSE);
7204         }
7205
7206         info_level_return = SVAL(pdata,16);
7207  
7208         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7209                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7210         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
7211                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7212         } else {
7213                 *pdata_return_size = 12;
7214         }
7215
7216         /* Realloc the data size */
7217         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7218         if (*ppdata == NULL) {
7219                 *pdata_return_size = 0;
7220                 return NT_STATUS_NO_MEMORY;
7221         }
7222         pdata = *ppdata;
7223
7224         SSVAL(pdata,0,NO_OPLOCK_RETURN);
7225         SSVAL(pdata,2,0); /* No fnum. */
7226         SIVAL(pdata,4,info); /* Was directory created. */
7227
7228         switch (info_level_return) {
7229                 case SMB_QUERY_FILE_UNIX_BASIC:
7230                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7231                         SSVAL(pdata,10,0); /* Padding. */
7232                         store_file_unix_basic(conn, pdata + 12, fsp,
7233                                               &smb_fname->st);
7234                         break;
7235                 case SMB_QUERY_FILE_UNIX_INFO2:
7236                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7237                         SSVAL(pdata,10,0); /* Padding. */
7238                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
7239                                                     &smb_fname->st);
7240                         break;
7241                 default:
7242                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7243                         SSVAL(pdata,10,0); /* Padding. */
7244                         break;
7245         }
7246
7247         return status;
7248 }
7249
7250 /****************************************************************************
7251  Open/Create a file with POSIX semantics.
7252 ****************************************************************************/
7253
7254 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7255 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7256
7257 static NTSTATUS smb_posix_open(connection_struct *conn,
7258                                struct smb_request *req,
7259                                 char **ppdata,
7260                                 int total_data,
7261                                 struct smb_filename *smb_fname,
7262                                 int *pdata_return_size)
7263 {
7264         bool extended_oplock_granted = False;
7265         char *pdata = *ppdata;
7266         uint32 flags = 0;
7267         uint32 wire_open_mode = 0;
7268         uint32 raw_unixmode = 0;
7269         uint32 mod_unixmode = 0;
7270         uint32 create_disp = 0;
7271         uint32 access_mask = 0;
7272         uint32 create_options = FILE_NON_DIRECTORY_FILE;
7273         NTSTATUS status = NT_STATUS_OK;
7274         mode_t unixmode = (mode_t)0;
7275         files_struct *fsp = NULL;
7276         int oplock_request = 0;
7277         int info = 0;
7278         uint16 info_level_return = 0;
7279
7280         if (total_data < 18) {
7281                 return NT_STATUS_INVALID_PARAMETER;
7282         }
7283
7284         flags = IVAL(pdata,0);
7285         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7286         if (oplock_request) {
7287                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7288         }
7289
7290         wire_open_mode = IVAL(pdata,4);
7291
7292         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7293                 return smb_posix_mkdir(conn, req,
7294                                         ppdata,
7295                                         total_data,
7296                                         smb_fname,
7297                                         pdata_return_size);
7298         }
7299
7300         switch (wire_open_mode & SMB_ACCMODE) {
7301                 case SMB_O_RDONLY:
7302                         access_mask = SMB_O_RDONLY_MAPPING;
7303                         break;
7304                 case SMB_O_WRONLY:
7305                         access_mask = SMB_O_WRONLY_MAPPING;
7306                         break;
7307                 case SMB_O_RDWR:
7308                         access_mask = (SMB_O_RDONLY_MAPPING|
7309                                         SMB_O_WRONLY_MAPPING);
7310                         break;
7311                 default:
7312                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7313                                 (unsigned int)wire_open_mode ));
7314                         return NT_STATUS_INVALID_PARAMETER;
7315         }
7316
7317         wire_open_mode &= ~SMB_ACCMODE;
7318
7319         /* First take care of O_CREAT|O_EXCL interactions. */
7320         switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7321                 case (SMB_O_CREAT | SMB_O_EXCL):
7322                         /* File exists fail. File not exist create. */
7323                         create_disp = FILE_CREATE;
7324                         break;
7325                 case SMB_O_CREAT:
7326                         /* File exists open. File not exist create. */
7327                         create_disp = FILE_OPEN_IF;
7328                         break;
7329                 case 0:
7330                         /* File exists open. File not exist fail. */
7331                         create_disp = FILE_OPEN;
7332                         break;
7333                 case SMB_O_EXCL:
7334                         /* O_EXCL on its own without O_CREAT is undefined. */
7335                 default:
7336                         DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7337                                 (unsigned int)wire_open_mode ));
7338                         return NT_STATUS_INVALID_PARAMETER;
7339         }
7340
7341         /* Next factor in the effects of O_TRUNC. */
7342         wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7343
7344         if (wire_open_mode & SMB_O_TRUNC) {
7345                 switch (create_disp) {
7346                         case FILE_CREATE:
7347                                 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7348                                 /* Leave create_disp alone as
7349                                    (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7350                                 */
7351                                 /* File exists fail. File not exist create. */
7352                                 break;
7353                         case FILE_OPEN_IF:
7354                                 /* SMB_O_CREAT | SMB_O_TRUNC */
7355                                 /* File exists overwrite. File not exist create. */
7356                                 create_disp = FILE_OVERWRITE_IF;
7357                                 break;
7358                         case FILE_OPEN:
7359                                 /* SMB_O_TRUNC */
7360                                 /* File exists overwrite. File not exist fail. */
7361                                 create_disp = FILE_OVERWRITE;
7362                                 break;
7363                         default:
7364                                 /* Cannot get here. */
7365                                 smb_panic("smb_posix_open: logic error");
7366                                 return NT_STATUS_INVALID_PARAMETER;
7367                 }
7368         }
7369
7370         raw_unixmode = IVAL(pdata,8);
7371         /* Next 4 bytes are not yet defined. */
7372
7373         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7374                                       (VALID_STAT(smb_fname->st) ?
7375                                           PERM_EXISTING_FILE : PERM_NEW_FILE),
7376                                       &unixmode);
7377
7378         if (!NT_STATUS_IS_OK(status)) {
7379                 return status;
7380         }
7381
7382         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7383
7384         if (wire_open_mode & SMB_O_SYNC) {
7385                 create_options |= FILE_WRITE_THROUGH;
7386         }
7387         if (wire_open_mode & SMB_O_APPEND) {
7388                 access_mask |= FILE_APPEND_DATA;
7389         }
7390         if (wire_open_mode & SMB_O_DIRECT) {
7391                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7392         }
7393
7394         if ((wire_open_mode & SMB_O_DIRECTORY) ||
7395                         VALID_STAT_OF_DIR(smb_fname->st)) {
7396                 if (access_mask != SMB_O_RDONLY_MAPPING) {
7397                         return NT_STATUS_FILE_IS_A_DIRECTORY;
7398                 }
7399                 create_options &= ~FILE_NON_DIRECTORY_FILE;
7400                 create_options |= FILE_DIRECTORY_FILE;
7401         }
7402
7403         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7404                 smb_fname_str_dbg(smb_fname),
7405                 (unsigned int)wire_open_mode,
7406                 (unsigned int)unixmode ));
7407
7408         status = SMB_VFS_CREATE_FILE(
7409                 conn,                                   /* conn */
7410                 req,                                    /* req */
7411                 0,                                      /* root_dir_fid */
7412                 smb_fname,                              /* fname */
7413                 access_mask,                            /* access_mask */
7414                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7415                     FILE_SHARE_DELETE),
7416                 create_disp,                            /* create_disposition*/
7417                 create_options,                         /* create_options */
7418                 mod_unixmode,                           /* file_attributes */
7419                 oplock_request,                         /* oplock_request */
7420                 0,                                      /* allocation_size */
7421                 0,                                      /* private_flags */
7422                 NULL,                                   /* sd */
7423                 NULL,                                   /* ea_list */
7424                 &fsp,                                   /* result */
7425                 &info);                                 /* pinfo */
7426
7427         if (!NT_STATUS_IS_OK(status)) {
7428                 return status;
7429         }
7430
7431         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7432                 extended_oplock_granted = True;
7433         }
7434
7435         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7436                 extended_oplock_granted = True;
7437         }
7438
7439         info_level_return = SVAL(pdata,16);
7440  
7441         /* Allocate the correct return size. */
7442
7443         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7444                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7445         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
7446                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7447         } else {
7448                 *pdata_return_size = 12;
7449         }
7450
7451         /* Realloc the data size */
7452         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7453         if (*ppdata == NULL) {
7454                 close_file(req, fsp, ERROR_CLOSE);
7455                 *pdata_return_size = 0;
7456                 return NT_STATUS_NO_MEMORY;
7457         }
7458         pdata = *ppdata;
7459
7460         if (extended_oplock_granted) {
7461                 if (flags & REQUEST_BATCH_OPLOCK) {
7462                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7463                 } else {
7464                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7465                 }
7466         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7467                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7468         } else {
7469                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7470         }
7471
7472         SSVAL(pdata,2,fsp->fnum);
7473         SIVAL(pdata,4,info); /* Was file created etc. */
7474
7475         switch (info_level_return) {
7476                 case SMB_QUERY_FILE_UNIX_BASIC:
7477                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7478                         SSVAL(pdata,10,0); /* padding. */
7479                         store_file_unix_basic(conn, pdata + 12, fsp,
7480                                               &smb_fname->st);
7481                         break;
7482                 case SMB_QUERY_FILE_UNIX_INFO2:
7483                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7484                         SSVAL(pdata,10,0); /* padding. */
7485                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
7486                                                     &smb_fname->st);
7487                         break;
7488                 default:
7489                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7490                         SSVAL(pdata,10,0); /* padding. */
7491                         break;
7492         }
7493         return NT_STATUS_OK;
7494 }
7495
7496 /****************************************************************************
7497  Delete a file with POSIX semantics.
7498 ****************************************************************************/
7499
7500 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7501                                  struct smb_request *req,
7502                                 const char *pdata,
7503                                 int total_data,
7504                                 struct smb_filename *smb_fname)
7505 {
7506         NTSTATUS status = NT_STATUS_OK;
7507         files_struct *fsp = NULL;
7508         uint16 flags = 0;
7509         char del = 1;
7510         int info = 0;
7511         int create_options = 0;
7512         int i;
7513         struct share_mode_lock *lck = NULL;
7514
7515         if (total_data < 2) {
7516                 return NT_STATUS_INVALID_PARAMETER;
7517         }
7518
7519         flags = SVAL(pdata,0);
7520
7521         if (!VALID_STAT(smb_fname->st)) {
7522                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7523         }
7524
7525         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7526                         !VALID_STAT_OF_DIR(smb_fname->st)) {
7527                 return NT_STATUS_NOT_A_DIRECTORY;
7528         }
7529
7530         DEBUG(10,("smb_posix_unlink: %s %s\n",
7531                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7532                 smb_fname_str_dbg(smb_fname)));
7533
7534         if (VALID_STAT_OF_DIR(smb_fname->st)) {
7535                 create_options |= FILE_DIRECTORY_FILE;
7536         }
7537
7538         status = SMB_VFS_CREATE_FILE(
7539                 conn,                                   /* conn */
7540                 req,                                    /* req */
7541                 0,                                      /* root_dir_fid */
7542                 smb_fname,                              /* fname */
7543                 DELETE_ACCESS,                          /* access_mask */
7544                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7545                     FILE_SHARE_DELETE),
7546                 FILE_OPEN,                              /* create_disposition*/
7547                 create_options,                         /* create_options */
7548                 FILE_FLAG_POSIX_SEMANTICS|0777,         /* file_attributes */
7549                 0,                                      /* oplock_request */
7550                 0,                                      /* allocation_size */
7551                 0,                                      /* private_flags */
7552                 NULL,                                   /* sd */
7553                 NULL,                                   /* ea_list */
7554                 &fsp,                                   /* result */
7555                 &info);                                 /* pinfo */
7556
7557         if (!NT_STATUS_IS_OK(status)) {
7558                 return status;
7559         }
7560
7561         /*
7562          * Don't lie to client. If we can't really delete due to
7563          * non-POSIX opens return SHARING_VIOLATION.
7564          */
7565
7566         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7567         if (lck == NULL) {
7568                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7569                           "lock for file %s\n", fsp_str_dbg(fsp)));
7570                 close_file(req, fsp, NORMAL_CLOSE);
7571                 return NT_STATUS_INVALID_PARAMETER;
7572         }
7573
7574         /*
7575          * See if others still have the file open. If this is the case, then
7576          * don't delete. If all opens are POSIX delete we can set the delete
7577          * on close disposition.
7578          */
7579         for (i=0; i<lck->data->num_share_modes; i++) {
7580                 struct share_mode_entry *e = &lck->data->share_modes[i];
7581                 if (is_valid_share_mode_entry(e)) {
7582                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7583                                 continue;
7584                         }
7585                         /* Fail with sharing violation. */
7586                         close_file(req, fsp, NORMAL_CLOSE);
7587                         TALLOC_FREE(lck);
7588                         return NT_STATUS_SHARING_VIOLATION;
7589                 }
7590         }
7591
7592         /*
7593          * Set the delete on close.
7594          */
7595         status = smb_set_file_disposition_info(conn,
7596                                                 &del,
7597                                                 1,
7598                                                 fsp,
7599                                                 smb_fname);
7600
7601         if (!NT_STATUS_IS_OK(status)) {
7602                 close_file(req, fsp, NORMAL_CLOSE);
7603                 TALLOC_FREE(lck);
7604                 return status;
7605         }
7606         TALLOC_FREE(lck);
7607         return close_file(req, fsp, NORMAL_CLOSE);
7608 }
7609
7610 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7611                                 struct smb_request *req,
7612                                 TALLOC_CTX *mem_ctx,
7613                                 uint16_t info_level,
7614                                 files_struct *fsp,
7615                                 struct smb_filename *smb_fname,
7616                                 char **ppdata, int total_data,
7617                                 int *ret_data_size)
7618 {
7619         char *pdata = *ppdata;
7620         NTSTATUS status = NT_STATUS_OK;
7621         int data_return_size = 0;
7622
7623         *ret_data_size = 0;
7624
7625         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7626                 return NT_STATUS_INVALID_LEVEL;
7627         }
7628
7629         if (!CAN_WRITE(conn)) {
7630                 /* Allow POSIX opens. The open path will deny
7631                  * any non-readonly opens. */
7632                 if (info_level != SMB_POSIX_PATH_OPEN) {
7633                         return NT_STATUS_DOS(ERRSRV, ERRaccess);
7634                 }
7635         }
7636
7637         DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7638                  "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7639                  fsp ? fsp->fnum : -1, info_level, total_data));
7640
7641         switch (info_level) {
7642
7643                 case SMB_INFO_STANDARD:
7644                 {
7645                         status = smb_set_info_standard(conn,
7646                                         pdata,
7647                                         total_data,
7648                                         fsp,
7649                                         smb_fname);
7650                         break;
7651                 }
7652
7653                 case SMB_INFO_SET_EA:
7654                 {
7655                         status = smb_info_set_ea(conn,
7656                                                 pdata,
7657                                                 total_data,
7658                                                 fsp,
7659                                                 smb_fname);
7660                         break;
7661                 }
7662
7663                 case SMB_SET_FILE_BASIC_INFO:
7664                 case SMB_FILE_BASIC_INFORMATION:
7665                 {
7666                         status = smb_set_file_basic_info(conn,
7667                                                         pdata,
7668                                                         total_data,
7669                                                         fsp,
7670                                                         smb_fname);
7671                         break;
7672                 }
7673
7674                 case SMB_FILE_ALLOCATION_INFORMATION:
7675                 case SMB_SET_FILE_ALLOCATION_INFO:
7676                 {
7677                         status = smb_set_file_allocation_info(conn, req,
7678                                                                 pdata,
7679                                                                 total_data,
7680                                                                 fsp,
7681                                                                 smb_fname);
7682                         break;
7683                 }
7684
7685                 case SMB_FILE_END_OF_FILE_INFORMATION:
7686                 case SMB_SET_FILE_END_OF_FILE_INFO:
7687                 {
7688                         /*
7689                          * XP/Win7 both fail after the createfile with
7690                          * SMB_SET_FILE_END_OF_FILE_INFO but not
7691                          * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7692                          * The level is known here, so pass it down
7693                          * appropriately.
7694                          */
7695                         bool should_fail =
7696                             (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7697
7698                         status = smb_set_file_end_of_file_info(conn, req,
7699                                                                 pdata,
7700                                                                 total_data,
7701                                                                 fsp,
7702                                                                 smb_fname,
7703                                                                 should_fail);
7704                         break;
7705                 }
7706
7707                 case SMB_FILE_DISPOSITION_INFORMATION:
7708                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7709                 {
7710 #if 0
7711                         /* JRA - We used to just ignore this on a path ? 
7712                          * Shouldn't this be invalid level on a pathname
7713                          * based call ?
7714                          */
7715                         if (tran_call != TRANSACT2_SETFILEINFO) {
7716                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7717                         }
7718 #endif
7719                         status = smb_set_file_disposition_info(conn,
7720                                                 pdata,
7721                                                 total_data,
7722                                                 fsp,
7723                                                 smb_fname);
7724                         break;
7725                 }
7726
7727                 case SMB_FILE_POSITION_INFORMATION:
7728                 {
7729                         status = smb_file_position_information(conn,
7730                                                 pdata,
7731                                                 total_data,
7732                                                 fsp);
7733                         break;
7734                 }
7735
7736                 case SMB_FILE_FULL_EA_INFORMATION:
7737                 {
7738                         status = smb_set_file_full_ea_info(conn,
7739                                                 pdata,
7740                                                 total_data,
7741                                                 fsp);
7742                         break;
7743                 }
7744
7745                 /* From tridge Samba4 : 
7746                  * MODE_INFORMATION in setfileinfo (I have no
7747                  * idea what "mode information" on a file is - it takes a value of 0,
7748                  * 2, 4 or 6. What could it be?).
7749                  */
7750
7751                 case SMB_FILE_MODE_INFORMATION:
7752                 {
7753                         status = smb_file_mode_information(conn,
7754                                                 pdata,
7755                                                 total_data);
7756                         break;
7757                 }
7758
7759                 /*
7760                  * CIFS UNIX extensions.
7761                  */
7762
7763                 case SMB_SET_FILE_UNIX_BASIC:
7764                 {
7765                         status = smb_set_file_unix_basic(conn, req,
7766                                                         pdata,
7767                                                         total_data,
7768                                                         fsp,
7769                                                         smb_fname);
7770                         break;
7771                 }
7772
7773                 case SMB_SET_FILE_UNIX_INFO2:
7774                 {
7775                         status = smb_set_file_unix_info2(conn, req,
7776                                                         pdata,
7777                                                         total_data,
7778                                                         fsp,
7779                                                         smb_fname);
7780                         break;
7781                 }
7782
7783                 case SMB_SET_FILE_UNIX_LINK:
7784                 {
7785                         if (fsp) {
7786                                 /* We must have a pathname for this. */
7787                                 return NT_STATUS_INVALID_LEVEL;
7788                         }
7789                         status = smb_set_file_unix_link(conn, req, pdata,
7790                                                         total_data, smb_fname);
7791                         break;
7792                 }
7793
7794                 case SMB_SET_FILE_UNIX_HLINK:
7795                 {
7796                         if (fsp) {
7797                                 /* We must have a pathname for this. */
7798                                 return NT_STATUS_INVALID_LEVEL;
7799                         }
7800                         status = smb_set_file_unix_hlink(conn, req,
7801                                                          pdata, total_data,
7802                                                          smb_fname);
7803                         break;
7804                 }
7805
7806                 case SMB_FILE_RENAME_INFORMATION:
7807                 {
7808                         status = smb_file_rename_information(conn, req,
7809                                                              pdata, total_data,
7810                                                              fsp, smb_fname);
7811                         break;
7812                 }
7813
7814                 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7815                 {
7816                         /* SMB2 rename information. */
7817                         status = smb2_file_rename_information(conn, req,
7818                                                              pdata, total_data,
7819                                                              fsp, smb_fname);
7820                         break;
7821                 }
7822
7823                 case SMB_FILE_LINK_INFORMATION:
7824                 {
7825                         status = smb_file_link_information(conn, req,
7826                                                         pdata, total_data,
7827                                                         fsp, smb_fname);
7828                         break;
7829                 }
7830
7831 #if defined(HAVE_POSIX_ACLS)
7832                 case SMB_SET_POSIX_ACL:
7833                 {
7834                         status = smb_set_posix_acl(conn,
7835                                                 pdata,
7836                                                 total_data,
7837                                                 fsp,
7838                                                 smb_fname);
7839                         break;
7840                 }
7841 #endif
7842
7843                 case SMB_SET_POSIX_LOCK:
7844                 {
7845                         if (!fsp) {
7846                                 return NT_STATUS_INVALID_LEVEL;
7847                         }
7848                         status = smb_set_posix_lock(conn, req,
7849                                                     pdata, total_data, fsp);
7850                         break;
7851                 }
7852
7853                 case SMB_POSIX_PATH_OPEN:
7854                 {
7855                         if (fsp) {
7856                                 /* We must have a pathname for this. */
7857                                 return NT_STATUS_INVALID_LEVEL;
7858                         }
7859
7860                         status = smb_posix_open(conn, req,
7861                                                 ppdata,
7862                                                 total_data,
7863                                                 smb_fname,
7864                                                 &data_return_size);
7865                         break;
7866                 }
7867
7868                 case SMB_POSIX_PATH_UNLINK:
7869                 {
7870                         if (fsp) {
7871                                 /* We must have a pathname for this. */
7872                                 return NT_STATUS_INVALID_LEVEL;
7873                         }
7874
7875                         status = smb_posix_unlink(conn, req,
7876                                                 pdata,
7877                                                 total_data,
7878                                                 smb_fname);
7879                         break;
7880                 }
7881
7882                 default:
7883                         return NT_STATUS_INVALID_LEVEL;
7884         }
7885
7886         if (!NT_STATUS_IS_OK(status)) {
7887                 return status;
7888         }
7889
7890         *ret_data_size = data_return_size;
7891         return NT_STATUS_OK;
7892 }
7893
7894 /****************************************************************************
7895  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7896 ****************************************************************************/
7897
7898 static void call_trans2setfilepathinfo(connection_struct *conn,
7899                                        struct smb_request *req,
7900                                        unsigned int tran_call,
7901                                        char **pparams, int total_params,
7902                                        char **ppdata, int total_data,
7903                                        unsigned int max_data_bytes)
7904 {
7905         char *params = *pparams;
7906         char *pdata = *ppdata;
7907         uint16 info_level;
7908         struct smb_filename *smb_fname = NULL;
7909         files_struct *fsp = NULL;
7910         NTSTATUS status = NT_STATUS_OK;
7911         int data_return_size = 0;
7912
7913         if (!params) {
7914                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7915                 return;
7916         }
7917
7918         if (tran_call == TRANSACT2_SETFILEINFO) {
7919                 if (total_params < 4) {
7920                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7921                         return;
7922                 }
7923
7924                 fsp = file_fsp(req, SVAL(params,0));
7925                 /* Basic check for non-null fsp. */
7926                 if (!check_fsp_open(conn, req, fsp)) {
7927                         return;
7928                 }
7929                 info_level = SVAL(params,2);
7930
7931                 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7932                                            &smb_fname);
7933                 if (!NT_STATUS_IS_OK(status)) {
7934                         reply_nterror(req, status);
7935                         return;
7936                 }
7937
7938                 if(fsp->fh->fd == -1) {
7939                         /*
7940                          * This is actually a SETFILEINFO on a directory
7941                          * handle (returned from an NT SMB). NT5.0 seems
7942                          * to do this call. JRA.
7943                          */
7944                         if (INFO_LEVEL_IS_UNIX(info_level)) {
7945                                 /* Always do lstat for UNIX calls. */
7946                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7947                                         DEBUG(3,("call_trans2setfilepathinfo: "
7948                                                  "SMB_VFS_LSTAT of %s failed "
7949                                                  "(%s)\n",
7950                                                  smb_fname_str_dbg(smb_fname),
7951                                                  strerror(errno)));
7952                                         reply_nterror(req, map_nt_error_from_unix(errno));
7953                                         return;
7954                                 }
7955                         } else {
7956                                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7957                                         DEBUG(3,("call_trans2setfilepathinfo: "
7958                                                  "fileinfo of %s failed (%s)\n",
7959                                                  smb_fname_str_dbg(smb_fname),
7960                                                  strerror(errno)));
7961                                         reply_nterror(req, map_nt_error_from_unix(errno));
7962                                         return;
7963                                 }
7964                         }
7965                 } else if (fsp->print_file) {
7966                         /*
7967                          * Doing a DELETE_ON_CLOSE should cancel a print job.
7968                          */
7969                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7970                                 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7971
7972                                 DEBUG(3,("call_trans2setfilepathinfo: "
7973                                          "Cancelling print job (%s)\n",
7974                                          fsp_str_dbg(fsp)));
7975
7976                                 SSVAL(params,0,0);
7977                                 send_trans2_replies(conn, req, params, 2,
7978                                                     *ppdata, 0,
7979                                                     max_data_bytes);
7980                                 return;
7981                         } else {
7982                                 reply_nterror(req,
7983                                         NT_STATUS_OBJECT_PATH_NOT_FOUND);
7984                                 return;
7985                         }
7986                 } else {
7987                         /*
7988                          * Original code - this is an open file.
7989                          */
7990                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7991                                 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7992                                          "of fnum %d failed (%s)\n", fsp->fnum,
7993                                          strerror(errno)));
7994                                 reply_nterror(req, map_nt_error_from_unix(errno));
7995                                 return;
7996                         }
7997                 }
7998         } else {
7999                 char *fname = NULL;
8000                 uint32_t ucf_flags = 0;
8001
8002                 /* set path info */
8003                 if (total_params < 7) {
8004                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8005                         return;
8006                 }
8007
8008                 info_level = SVAL(params,0);
8009                 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8010                                 total_params - 6, STR_TERMINATE,
8011                                 &status);
8012                 if (!NT_STATUS_IS_OK(status)) {
8013                         reply_nterror(req, status);
8014                         return;
8015                 }
8016
8017                 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8018                                 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8019                                 info_level == SMB_FILE_RENAME_INFORMATION ||
8020                                 info_level == SMB_POSIX_PATH_UNLINK) {
8021                         ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8022                 }
8023
8024                 status = filename_convert(req, conn,
8025                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
8026                                          fname,
8027                                          ucf_flags,
8028                                          NULL,
8029                                          &smb_fname);
8030                 if (!NT_STATUS_IS_OK(status)) {
8031                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8032                                 reply_botherror(req,
8033                                                 NT_STATUS_PATH_NOT_COVERED,
8034                                                 ERRSRV, ERRbadpath);
8035                                 return;
8036                         }
8037                         reply_nterror(req, status);
8038                         return;
8039                 }
8040
8041                 if (INFO_LEVEL_IS_UNIX(info_level)) {
8042                         /*
8043                          * For CIFS UNIX extensions the target name may not exist.
8044                          */
8045
8046                         /* Always do lstat for UNIX calls. */
8047                         SMB_VFS_LSTAT(conn, smb_fname);
8048
8049                 } else if (!VALID_STAT(smb_fname->st) &&
8050                            SMB_VFS_STAT(conn, smb_fname)) {
8051                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8052                                  "%s failed (%s)\n",
8053                                  smb_fname_str_dbg(smb_fname),
8054                                  strerror(errno)));
8055                         reply_nterror(req, map_nt_error_from_unix(errno));
8056                         return;
8057                 }
8058         }
8059
8060         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8061                  "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8062                  fsp ? fsp->fnum : -1, info_level,total_data));
8063
8064         /* Realloc the parameter size */
8065         *pparams = (char *)SMB_REALLOC(*pparams,2);
8066         if (*pparams == NULL) {
8067                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8068                 return;
8069         }
8070         params = *pparams;
8071
8072         SSVAL(params,0,0);
8073
8074         status = smbd_do_setfilepathinfo(conn, req, req,
8075                                          info_level,
8076                                          fsp,
8077                                          smb_fname,
8078                                          ppdata, total_data,
8079                                          &data_return_size);
8080         if (!NT_STATUS_IS_OK(status)) {
8081                 if (open_was_deferred(req->sconn, req->mid)) {
8082                         /* We have re-scheduled this call. */
8083                         return;
8084                 }
8085                 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8086                         /* We have re-scheduled this call. */
8087                         return;
8088                 }
8089                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8090                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8091                                         ERRSRV, ERRbadpath);
8092                         return;
8093                 }
8094                 if (info_level == SMB_POSIX_PATH_OPEN) {
8095                         reply_openerror(req, status);
8096                         return;
8097                 }
8098
8099                 reply_nterror(req, status);
8100                 return;
8101         }
8102
8103         send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8104                             max_data_bytes);
8105
8106         return;
8107 }
8108
8109 /****************************************************************************
8110  Reply to a TRANS2_MKDIR (make directory with extended attributes).
8111 ****************************************************************************/
8112
8113 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8114                              char **pparams, int total_params,
8115                              char **ppdata, int total_data,
8116                              unsigned int max_data_bytes)
8117 {
8118         struct smb_filename *smb_dname = NULL;
8119         char *params = *pparams;
8120         char *pdata = *ppdata;
8121         char *directory = NULL;
8122         NTSTATUS status = NT_STATUS_OK;
8123         struct ea_list *ea_list = NULL;
8124         TALLOC_CTX *ctx = talloc_tos();
8125
8126         if (!CAN_WRITE(conn)) {
8127                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8128                 return;
8129         }
8130
8131         if (total_params < 5) {
8132                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8133                 return;
8134         }
8135
8136         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8137                         total_params - 4, STR_TERMINATE,
8138                         &status);
8139         if (!NT_STATUS_IS_OK(status)) {
8140                 reply_nterror(req, status);
8141                 return;
8142         }
8143
8144         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8145
8146         status = filename_convert(ctx,
8147                                 conn,
8148                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
8149                                 directory,
8150                                 0,
8151                                 NULL,
8152                                 &smb_dname);
8153
8154         if (!NT_STATUS_IS_OK(status)) {
8155                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8156                         reply_botherror(req,
8157                                 NT_STATUS_PATH_NOT_COVERED,
8158                                 ERRSRV, ERRbadpath);
8159                         return;
8160                 }
8161                 reply_nterror(req, status);
8162                 return;
8163         }
8164
8165         /*
8166          * OS/2 workplace shell seems to send SET_EA requests of "null"
8167          * length (4 bytes containing IVAL 4).
8168          * They seem to have no effect. Bug #3212. JRA.
8169          */
8170
8171         if (total_data && (total_data != 4)) {
8172                 /* Any data in this call is an EA list. */
8173                 if (total_data < 10) {
8174                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8175                         goto out;
8176                 }
8177
8178                 if (IVAL(pdata,0) > total_data) {
8179                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8180                                 IVAL(pdata,0), (unsigned int)total_data));
8181                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8182                         goto out;
8183                 }
8184
8185                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8186                                        total_data - 4);
8187                 if (!ea_list) {
8188                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8189                         goto out;
8190                 }
8191
8192                 if (!lp_ea_support(SNUM(conn))) {
8193                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8194                         goto out;
8195                 }
8196         }
8197         /* If total_data == 4 Windows doesn't care what values
8198          * are placed in that field, it just ignores them.
8199          * The System i QNTC IBM SMB client puts bad values here,
8200          * so ignore them. */
8201
8202         status = create_directory(conn, req, smb_dname);
8203
8204         if (!NT_STATUS_IS_OK(status)) {
8205                 reply_nterror(req, status);
8206                 goto out;
8207         }
8208
8209         /* Try and set any given EA. */
8210         if (ea_list) {
8211                 status = set_ea(conn, NULL, smb_dname, ea_list);
8212                 if (!NT_STATUS_IS_OK(status)) {
8213                         reply_nterror(req, status);
8214                         goto out;
8215                 }
8216         }
8217
8218         /* Realloc the parameter and data sizes */
8219         *pparams = (char *)SMB_REALLOC(*pparams,2);
8220         if(*pparams == NULL) {
8221                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8222                 goto out;
8223         }
8224         params = *pparams;
8225
8226         SSVAL(params,0,0);
8227
8228         send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8229
8230  out:
8231         TALLOC_FREE(smb_dname);
8232         return;
8233 }
8234
8235 /****************************************************************************
8236  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8237  We don't actually do this - we just send a null response.
8238 ****************************************************************************/
8239
8240 static void call_trans2findnotifyfirst(connection_struct *conn,
8241                                        struct smb_request *req,
8242                                        char **pparams, int total_params,
8243                                        char **ppdata, int total_data,
8244                                        unsigned int max_data_bytes)
8245 {
8246         char *params = *pparams;
8247         uint16 info_level;
8248
8249         if (total_params < 6) {
8250                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8251                 return;
8252         }
8253
8254         info_level = SVAL(params,4);
8255         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8256
8257         switch (info_level) {
8258                 case 1:
8259                 case 2:
8260                         break;
8261                 default:
8262                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8263                         return;
8264         }
8265
8266         /* Realloc the parameter and data sizes */
8267         *pparams = (char *)SMB_REALLOC(*pparams,6);
8268         if (*pparams == NULL) {
8269                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8270                 return;
8271         }
8272         params = *pparams;
8273
8274         SSVAL(params,0,fnf_handle);
8275         SSVAL(params,2,0); /* No changes */
8276         SSVAL(params,4,0); /* No EA errors */
8277
8278         fnf_handle++;
8279
8280         if(fnf_handle == 0)
8281                 fnf_handle = 257;
8282
8283         send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8284
8285         return;
8286 }
8287
8288 /****************************************************************************
8289  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
8290  changes). Currently this does nothing.
8291 ****************************************************************************/
8292
8293 static void call_trans2findnotifynext(connection_struct *conn,
8294                                       struct smb_request *req,
8295                                       char **pparams, int total_params,
8296                                       char **ppdata, int total_data,
8297                                       unsigned int max_data_bytes)
8298 {
8299         char *params = *pparams;
8300
8301         DEBUG(3,("call_trans2findnotifynext\n"));
8302
8303         /* Realloc the parameter and data sizes */
8304         *pparams = (char *)SMB_REALLOC(*pparams,4);
8305         if (*pparams == NULL) {
8306                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8307                 return;
8308         }
8309         params = *pparams;
8310
8311         SSVAL(params,0,0); /* No changes */
8312         SSVAL(params,2,0); /* No EA errors */
8313
8314         send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8315
8316         return;
8317 }
8318
8319 /****************************************************************************
8320  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8321 ****************************************************************************/
8322
8323 static void call_trans2getdfsreferral(connection_struct *conn,
8324                                       struct smb_request *req,
8325                                       char **pparams, int total_params,
8326                                       char **ppdata, int total_data,
8327                                       unsigned int max_data_bytes)
8328 {
8329         char *params = *pparams;
8330         char *pathname = NULL;
8331         int reply_size = 0;
8332         int max_referral_level;
8333         NTSTATUS status = NT_STATUS_OK;
8334         TALLOC_CTX *ctx = talloc_tos();
8335
8336         DEBUG(10,("call_trans2getdfsreferral\n"));
8337
8338         if (total_params < 3) {
8339                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8340                 return;
8341         }
8342
8343         max_referral_level = SVAL(params,0);
8344
8345         if(!lp_host_msdfs()) {
8346                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8347                 return;
8348         }
8349
8350         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8351                     total_params - 2, STR_TERMINATE);
8352         if (!pathname) {
8353                 reply_nterror(req, NT_STATUS_NOT_FOUND);
8354                 return;
8355         }
8356         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8357                                             ppdata,&status)) < 0) {
8358                 reply_nterror(req, status);
8359                 return;
8360         }
8361
8362         SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8363               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8364         send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8365
8366         return;
8367 }
8368
8369 #define LMCAT_SPL       0x53
8370 #define LMFUNC_GETJOBID 0x60
8371
8372 /****************************************************************************
8373  Reply to a TRANS2_IOCTL - used for OS/2 printing.
8374 ****************************************************************************/
8375
8376 static void call_trans2ioctl(connection_struct *conn,
8377                              struct smb_request *req,
8378                              char **pparams, int total_params,
8379                              char **ppdata, int total_data,
8380                              unsigned int max_data_bytes)
8381 {
8382         char *pdata = *ppdata;
8383         files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8384
8385         /* check for an invalid fid before proceeding */
8386
8387         if (!fsp) {
8388                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8389                 return;
8390         }
8391
8392         if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8393             && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8394                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8395                 if (*ppdata == NULL) {
8396                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8397                         return;
8398                 }
8399                 pdata = *ppdata;
8400
8401                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8402                         CAN ACCEPT THIS IN UNICODE. JRA. */
8403
8404                 /* Job number */
8405                 if (fsp->print_file) {
8406                         SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8407                 } else {
8408                         SSVAL(pdata, 0, 0);
8409                 }
8410                 srvstr_push(pdata, req->flags2, pdata + 2,
8411                             lp_netbios_name(), 15,
8412                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8413                 srvstr_push(pdata, req->flags2, pdata+18,
8414                             lp_servicename(SNUM(conn)), 13,
8415                             STR_ASCII|STR_TERMINATE); /* Service name */
8416                 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8417                                     max_data_bytes);
8418                 return;
8419         }
8420
8421         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8422         reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8423 }
8424
8425 /****************************************************************************
8426  Reply to a SMBfindclose (stop trans2 directory search).
8427 ****************************************************************************/
8428
8429 void reply_findclose(struct smb_request *req)
8430 {
8431         int dptr_num;
8432         struct smbd_server_connection *sconn = req->sconn;
8433
8434         START_PROFILE(SMBfindclose);
8435
8436         if (req->wct < 1) {
8437                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8438                 END_PROFILE(SMBfindclose);
8439                 return;
8440         }
8441
8442         dptr_num = SVALS(req->vwv+0, 0);
8443
8444         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8445
8446         dptr_close(sconn, &dptr_num);
8447
8448         reply_outbuf(req, 0, 0);
8449
8450         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8451
8452         END_PROFILE(SMBfindclose);
8453         return;
8454 }
8455
8456 /****************************************************************************
8457  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8458 ****************************************************************************/
8459
8460 void reply_findnclose(struct smb_request *req)
8461 {
8462         int dptr_num;
8463
8464         START_PROFILE(SMBfindnclose);
8465
8466         if (req->wct < 1) {
8467                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8468                 END_PROFILE(SMBfindnclose);
8469                 return;
8470         }
8471
8472         dptr_num = SVAL(req->vwv+0, 0);
8473
8474         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8475
8476         /* We never give out valid handles for a 
8477            findnotifyfirst - so any dptr_num is ok here. 
8478            Just ignore it. */
8479
8480         reply_outbuf(req, 0, 0);
8481
8482         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8483
8484         END_PROFILE(SMBfindnclose);
8485         return;
8486 }
8487
8488 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8489                           struct trans_state *state)
8490 {
8491         if (get_Protocol() >= PROTOCOL_NT1) {
8492                 req->flags2 |= 0x40; /* IS_LONG_NAME */
8493                 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8494         }
8495
8496         if (conn->encrypt_level == Required && !req->encrypted) {
8497                 if (state->call != TRANSACT2_QFSINFO &&
8498                                 state->call != TRANSACT2_SETFSINFO) {
8499                         DEBUG(0,("handle_trans2: encryption required "
8500                                 "with call 0x%x\n",
8501                                 (unsigned int)state->call));
8502                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8503                         return;
8504                 }
8505         }
8506
8507         SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8508
8509         /* Now we must call the relevant TRANS2 function */
8510         switch(state->call)  {
8511         case TRANSACT2_OPEN:
8512         {
8513                 START_PROFILE(Trans2_open);
8514                 call_trans2open(conn, req,
8515                                 &state->param, state->total_param,
8516                                 &state->data, state->total_data,
8517                                 state->max_data_return);
8518                 END_PROFILE(Trans2_open);
8519                 break;
8520         }
8521
8522         case TRANSACT2_FINDFIRST:
8523         {
8524                 START_PROFILE(Trans2_findfirst);
8525                 call_trans2findfirst(conn, req,
8526                                      &state->param, state->total_param,
8527                                      &state->data, state->total_data,
8528                                      state->max_data_return);
8529                 END_PROFILE(Trans2_findfirst);
8530                 break;
8531         }
8532
8533         case TRANSACT2_FINDNEXT:
8534         {
8535                 START_PROFILE(Trans2_findnext);
8536                 call_trans2findnext(conn, req,
8537                                     &state->param, state->total_param,
8538                                     &state->data, state->total_data,
8539                                     state->max_data_return);
8540                 END_PROFILE(Trans2_findnext);
8541                 break;
8542         }
8543
8544         case TRANSACT2_QFSINFO:
8545         {
8546                 START_PROFILE(Trans2_qfsinfo);
8547                 call_trans2qfsinfo(conn, req,
8548                                    &state->param, state->total_param,
8549                                    &state->data, state->total_data,
8550                                    state->max_data_return);
8551                 END_PROFILE(Trans2_qfsinfo);
8552             break;
8553         }
8554
8555         case TRANSACT2_SETFSINFO:
8556         {
8557                 START_PROFILE(Trans2_setfsinfo);
8558                 call_trans2setfsinfo(conn, req,
8559                                      &state->param, state->total_param,
8560                                      &state->data, state->total_data,
8561                                      state->max_data_return);
8562                 END_PROFILE(Trans2_setfsinfo);
8563                 break;
8564         }
8565
8566         case TRANSACT2_QPATHINFO:
8567         case TRANSACT2_QFILEINFO:
8568         {
8569                 START_PROFILE(Trans2_qpathinfo);
8570                 call_trans2qfilepathinfo(conn, req, state->call,
8571                                          &state->param, state->total_param,
8572                                          &state->data, state->total_data,
8573                                          state->max_data_return);
8574                 END_PROFILE(Trans2_qpathinfo);
8575                 break;
8576         }
8577
8578         case TRANSACT2_SETPATHINFO:
8579         case TRANSACT2_SETFILEINFO:
8580         {
8581                 START_PROFILE(Trans2_setpathinfo);
8582                 call_trans2setfilepathinfo(conn, req, state->call,
8583                                            &state->param, state->total_param,
8584                                            &state->data, state->total_data,
8585                                            state->max_data_return);
8586                 END_PROFILE(Trans2_setpathinfo);
8587                 break;
8588         }
8589
8590         case TRANSACT2_FINDNOTIFYFIRST:
8591         {
8592                 START_PROFILE(Trans2_findnotifyfirst);
8593                 call_trans2findnotifyfirst(conn, req,
8594                                            &state->param, state->total_param,
8595                                            &state->data, state->total_data,
8596                                            state->max_data_return);
8597                 END_PROFILE(Trans2_findnotifyfirst);
8598                 break;
8599         }
8600
8601         case TRANSACT2_FINDNOTIFYNEXT:
8602         {
8603                 START_PROFILE(Trans2_findnotifynext);
8604                 call_trans2findnotifynext(conn, req,
8605                                           &state->param, state->total_param,
8606                                           &state->data, state->total_data,
8607                                           state->max_data_return);
8608                 END_PROFILE(Trans2_findnotifynext);
8609                 break;
8610         }
8611
8612         case TRANSACT2_MKDIR:
8613         {
8614                 START_PROFILE(Trans2_mkdir);
8615                 call_trans2mkdir(conn, req,
8616                                  &state->param, state->total_param,
8617                                  &state->data, state->total_data,
8618                                  state->max_data_return);
8619                 END_PROFILE(Trans2_mkdir);
8620                 break;
8621         }
8622
8623         case TRANSACT2_GET_DFS_REFERRAL:
8624         {
8625                 START_PROFILE(Trans2_get_dfs_referral);
8626                 call_trans2getdfsreferral(conn, req,
8627                                           &state->param, state->total_param,
8628                                           &state->data, state->total_data,
8629                                           state->max_data_return);
8630                 END_PROFILE(Trans2_get_dfs_referral);
8631                 break;
8632         }
8633
8634         case TRANSACT2_IOCTL:
8635         {
8636                 START_PROFILE(Trans2_ioctl);
8637                 call_trans2ioctl(conn, req,
8638                                  &state->param, state->total_param,
8639                                  &state->data, state->total_data,
8640                                  state->max_data_return);
8641                 END_PROFILE(Trans2_ioctl);
8642                 break;
8643         }
8644
8645         default:
8646                 /* Error in request */
8647                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8648                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8649         }
8650 }
8651
8652 /****************************************************************************
8653  Reply to a SMBtrans2.
8654  ****************************************************************************/
8655
8656 void reply_trans2(struct smb_request *req)
8657 {
8658         connection_struct *conn = req->conn;
8659         unsigned int dsoff;
8660         unsigned int dscnt;
8661         unsigned int psoff;
8662         unsigned int pscnt;
8663         unsigned int tran_call;
8664         struct trans_state *state;
8665         NTSTATUS result;
8666
8667         START_PROFILE(SMBtrans2);
8668
8669         if (req->wct < 14) {
8670                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8671                 END_PROFILE(SMBtrans2);
8672                 return;
8673         }
8674
8675         dsoff = SVAL(req->vwv+12, 0);
8676         dscnt = SVAL(req->vwv+11, 0);
8677         psoff = SVAL(req->vwv+10, 0);
8678         pscnt = SVAL(req->vwv+9, 0);
8679         tran_call = SVAL(req->vwv+14, 0);
8680
8681         result = allow_new_trans(conn->pending_trans, req->mid);
8682         if (!NT_STATUS_IS_OK(result)) {
8683                 DEBUG(2, ("Got invalid trans2 request: %s\n",
8684                           nt_errstr(result)));
8685                 reply_nterror(req, result);
8686                 END_PROFILE(SMBtrans2);
8687                 return;
8688         }
8689
8690         if (IS_IPC(conn)) {
8691                 switch (tran_call) {
8692                 /* List the allowed trans2 calls on IPC$ */
8693                 case TRANSACT2_OPEN:
8694                 case TRANSACT2_GET_DFS_REFERRAL:
8695                 case TRANSACT2_QFILEINFO:
8696                 case TRANSACT2_QFSINFO:
8697                 case TRANSACT2_SETFSINFO:
8698                         break;
8699                 default:
8700                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8701                         END_PROFILE(SMBtrans2);
8702                         return;
8703                 }
8704         }
8705
8706         if ((state = talloc(conn, struct trans_state)) == NULL) {
8707                 DEBUG(0, ("talloc failed\n"));
8708                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8709                 END_PROFILE(SMBtrans2);
8710                 return;
8711         }
8712
8713         state->cmd = SMBtrans2;
8714
8715         state->mid = req->mid;
8716         state->vuid = req->vuid;
8717         state->setup_count = SVAL(req->vwv+13, 0);
8718         state->setup = NULL;
8719         state->total_param = SVAL(req->vwv+0, 0);
8720         state->param = NULL;
8721         state->total_data =  SVAL(req->vwv+1, 0);
8722         state->data = NULL;
8723         state->max_param_return = SVAL(req->vwv+2, 0);
8724         state->max_data_return  = SVAL(req->vwv+3, 0);
8725         state->max_setup_return = SVAL(req->vwv+4, 0);
8726         state->close_on_completion = BITSETW(req->vwv+5, 0);
8727         state->one_way = BITSETW(req->vwv+5, 1);
8728
8729         state->call = tran_call;
8730
8731         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8732            is so as a sanity check */
8733         if (state->setup_count != 1) {
8734                 /*
8735                  * Need to have rc=0 for ioctl to get job id for OS/2.
8736                  *  Network printing will fail if function is not successful.
8737                  *  Similar function in reply.c will be used if protocol
8738                  *  is LANMAN1.0 instead of LM1.2X002.
8739                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
8740                  *  outbuf doesn't have to be set(only job id is used).
8741                  */
8742                 if ( (state->setup_count == 4)
8743                      && (tran_call == TRANSACT2_IOCTL)
8744                      && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8745                      && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8746                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8747                 } else {
8748                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8749                         DEBUG(2,("Transaction is %d\n",tran_call));
8750                         TALLOC_FREE(state);
8751                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8752                         END_PROFILE(SMBtrans2);
8753                         return;
8754                 }
8755         }
8756
8757         if ((dscnt > state->total_data) || (pscnt > state->total_param))
8758                 goto bad_param;
8759
8760         if (state->total_data) {
8761
8762                 if (trans_oob(state->total_data, 0, dscnt)
8763                     || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8764                         goto bad_param;
8765                 }
8766
8767                 /* Can't use talloc here, the core routines do realloc on the
8768                  * params and data. */
8769                 state->data = (char *)SMB_MALLOC(state->total_data);
8770                 if (state->data == NULL) {
8771                         DEBUG(0,("reply_trans2: data malloc fail for %u "
8772                                  "bytes !\n", (unsigned int)state->total_data));
8773                         TALLOC_FREE(state);
8774                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8775                         END_PROFILE(SMBtrans2);
8776                         return;
8777                 }
8778
8779                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8780         }
8781
8782         if (state->total_param) {
8783
8784                 if (trans_oob(state->total_param, 0, pscnt)
8785                     || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8786                         goto bad_param;
8787                 }
8788
8789                 /* Can't use talloc here, the core routines do realloc on the
8790                  * params and data. */
8791                 state->param = (char *)SMB_MALLOC(state->total_param);
8792                 if (state->param == NULL) {
8793                         DEBUG(0,("reply_trans: param malloc fail for %u "
8794                                  "bytes !\n", (unsigned int)state->total_param));
8795                         SAFE_FREE(state->data);
8796                         TALLOC_FREE(state);
8797                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8798                         END_PROFILE(SMBtrans2);
8799                         return;
8800                 } 
8801
8802                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8803         }
8804
8805         state->received_data  = dscnt;
8806         state->received_param = pscnt;
8807
8808         if ((state->received_param == state->total_param) &&
8809             (state->received_data == state->total_data)) {
8810
8811                 handle_trans2(conn, req, state);
8812
8813                 SAFE_FREE(state->data);
8814                 SAFE_FREE(state->param);
8815                 TALLOC_FREE(state);
8816                 END_PROFILE(SMBtrans2);
8817                 return;
8818         }
8819
8820         DLIST_ADD(conn->pending_trans, state);
8821
8822         /* We need to send an interim response then receive the rest
8823            of the parameter/data bytes */
8824         reply_outbuf(req, 0, 0);
8825         show_msg((char *)req->outbuf);
8826         END_PROFILE(SMBtrans2);
8827         return;
8828
8829   bad_param:
8830
8831         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8832         SAFE_FREE(state->data);
8833         SAFE_FREE(state->param);
8834         TALLOC_FREE(state);
8835         END_PROFILE(SMBtrans2);
8836         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8837 }
8838
8839
8840 /****************************************************************************
8841  Reply to a SMBtranss2
8842  ****************************************************************************/
8843
8844 void reply_transs2(struct smb_request *req)
8845 {
8846         connection_struct *conn = req->conn;
8847         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8848         struct trans_state *state;
8849
8850         START_PROFILE(SMBtranss2);
8851
8852         show_msg((const char *)req->inbuf);
8853
8854         if (req->wct < 8) {
8855                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8856                 END_PROFILE(SMBtranss2);
8857                 return;
8858         }
8859
8860         for (state = conn->pending_trans; state != NULL;
8861              state = state->next) {
8862                 if (state->mid == req->mid) {
8863                         break;
8864                 }
8865         }
8866
8867         if ((state == NULL) || (state->cmd != SMBtrans2)) {
8868                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8869                 END_PROFILE(SMBtranss2);
8870                 return;
8871         }
8872
8873         /* Revise state->total_param and state->total_data in case they have
8874            changed downwards */
8875
8876         if (SVAL(req->vwv+0, 0) < state->total_param)
8877                 state->total_param = SVAL(req->vwv+0, 0);
8878         if (SVAL(req->vwv+1, 0) < state->total_data)
8879                 state->total_data = SVAL(req->vwv+1, 0);
8880
8881         pcnt = SVAL(req->vwv+2, 0);
8882         poff = SVAL(req->vwv+3, 0);
8883         pdisp = SVAL(req->vwv+4, 0);
8884
8885         dcnt = SVAL(req->vwv+5, 0);
8886         doff = SVAL(req->vwv+6, 0);
8887         ddisp = SVAL(req->vwv+7, 0);
8888
8889         state->received_param += pcnt;
8890         state->received_data += dcnt;
8891
8892         if ((state->received_data > state->total_data) ||
8893             (state->received_param > state->total_param))
8894                 goto bad_param;
8895
8896         if (pcnt) {
8897                 if (trans_oob(state->total_param, pdisp, pcnt)
8898                     || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8899                         goto bad_param;
8900                 }
8901                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8902         }
8903
8904         if (dcnt) {
8905                 if (trans_oob(state->total_data, ddisp, dcnt)
8906                     || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8907                         goto bad_param;
8908                 }
8909                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8910         }
8911
8912         if ((state->received_param < state->total_param) ||
8913             (state->received_data < state->total_data)) {
8914                 END_PROFILE(SMBtranss2);
8915                 return;
8916         }
8917
8918         handle_trans2(conn, req, state);
8919
8920         DLIST_REMOVE(conn->pending_trans, state);
8921         SAFE_FREE(state->data);
8922         SAFE_FREE(state->param);
8923         TALLOC_FREE(state);
8924
8925         END_PROFILE(SMBtranss2);
8926         return;
8927
8928   bad_param:
8929
8930         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8931         DLIST_REMOVE(conn->pending_trans, state);
8932         SAFE_FREE(state->data);
8933         SAFE_FREE(state->param);
8934         TALLOC_FREE(state);
8935         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8936         END_PROFILE(SMBtranss2);
8937         return;
8938 }