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