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