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