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