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