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