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