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