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