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