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