s3: Remove the now unused fname parameter from filename_convert()
[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         if (!NT_STATUS_IS_OK(status)) {
1033                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1034                         reply_botherror(req,
1035                                 NT_STATUS_PATH_NOT_COVERED,
1036                                 ERRSRV, ERRbadpath);
1037                         goto out;
1038                 }
1039                 reply_nterror(req, status);
1040                 goto out;
1041         }
1042
1043         if (open_ofun == 0) {
1044                 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1045                 goto out;
1046         }
1047
1048         if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1049                                          &access_mask, &share_mode,
1050                                          &create_disposition,
1051                                          &create_options)) {
1052                 reply_doserror(req, ERRDOS, ERRbadaccess);
1053                 goto out;
1054         }
1055
1056         /* Any data in this call is an EA list. */
1057         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1058                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1059                 goto out;
1060         }
1061
1062         if (total_data != 4) {
1063                 if (total_data < 10) {
1064                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1065                         goto out;
1066                 }
1067
1068                 if (IVAL(pdata,0) > total_data) {
1069                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1070                                 IVAL(pdata,0), (unsigned int)total_data));
1071                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1072                         goto out;
1073                 }
1074
1075                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1076                                        total_data - 4);
1077                 if (!ea_list) {
1078                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1079                         goto out;
1080                 }
1081         } else if (IVAL(pdata,0) != 4) {
1082                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1083                 goto out;
1084         }
1085
1086         status = SMB_VFS_CREATE_FILE(
1087                 conn,                                   /* conn */
1088                 req,                                    /* req */
1089                 0,                                      /* root_dir_fid */
1090                 smb_fname,                              /* fname */
1091                 access_mask,                            /* access_mask */
1092                 share_mode,                             /* share_access */
1093                 create_disposition,                     /* create_disposition*/
1094                 create_options,                         /* create_options */
1095                 open_attr,                              /* file_attributes */
1096                 oplock_request,                         /* oplock_request */
1097                 open_size,                              /* allocation_size */
1098                 NULL,                                   /* sd */
1099                 ea_list,                                /* ea_list */
1100                 &fsp,                                   /* result */
1101                 &smb_action);                           /* psbuf */
1102
1103         if (!NT_STATUS_IS_OK(status)) {
1104                 if (open_was_deferred(req->mid)) {
1105                         /* We have re-scheduled this call. */
1106                         goto out;
1107                 }
1108                 reply_openerror(req, status);
1109                 goto out;
1110         }
1111
1112         size = get_file_size_stat(&smb_fname->st);
1113         fattr = dos_mode(conn, smb_fname);
1114         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1115         inode = smb_fname->st.st_ex_ino;
1116         if (fattr & aDIR) {
1117                 close_file(req, fsp, ERROR_CLOSE);
1118                 reply_doserror(req, ERRDOS,ERRnoaccess);
1119                 goto out;
1120         }
1121
1122         /* Realloc the size of parameters and data we will return */
1123         *pparams = (char *)SMB_REALLOC(*pparams, 30);
1124         if(*pparams == NULL ) {
1125                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1126                 goto out;
1127         }
1128         params = *pparams;
1129
1130         SSVAL(params,0,fsp->fnum);
1131         SSVAL(params,2,fattr);
1132         srv_put_dos_date2(params,4, mtime);
1133         SIVAL(params,8, (uint32)size);
1134         SSVAL(params,12,deny_mode);
1135         SSVAL(params,14,0); /* open_type - file or directory. */
1136         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1137
1138         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1139                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1140         }
1141
1142         SSVAL(params,18,smb_action);
1143
1144         /*
1145          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1146          */
1147         SIVAL(params,20,inode);
1148         SSVAL(params,24,0); /* Padding. */
1149         if (flags & 8) {
1150                 uint32 ea_size = estimate_ea_size(conn, fsp,
1151                                                   fsp->fsp_name->base_name);
1152                 SIVAL(params, 26, ea_size);
1153         } else {
1154                 SIVAL(params, 26, 0);
1155         }
1156
1157         /* Send the required number of replies */
1158         send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1159  out:
1160         TALLOC_FREE(smb_fname);
1161 }
1162
1163 /*********************************************************
1164  Routine to check if a given string matches exactly.
1165  as a special case a mask of "." does NOT match. That
1166  is required for correct wildcard semantics
1167  Case can be significant or not.
1168 **********************************************************/
1169
1170 static bool exact_match(connection_struct *conn,
1171                 const char *str,
1172                 const char *mask)
1173 {
1174         if (mask[0] == '.' && mask[1] == 0)
1175                 return False;
1176         if (dptr_has_wild(conn->dirptr)) {
1177                 return False;
1178         }
1179         if (conn->case_sensitive)
1180                 return strcmp(str,mask)==0;
1181         else
1182                 return StrCaseCmp(str,mask) == 0;
1183 }
1184
1185 /****************************************************************************
1186  Return the filetype for UNIX extensions.
1187 ****************************************************************************/
1188
1189 static uint32 unix_filetype(mode_t mode)
1190 {
1191         if(S_ISREG(mode))
1192                 return UNIX_TYPE_FILE;
1193         else if(S_ISDIR(mode))
1194                 return UNIX_TYPE_DIR;
1195 #ifdef S_ISLNK
1196         else if(S_ISLNK(mode))
1197                 return UNIX_TYPE_SYMLINK;
1198 #endif
1199 #ifdef S_ISCHR
1200         else if(S_ISCHR(mode))
1201                 return UNIX_TYPE_CHARDEV;
1202 #endif
1203 #ifdef S_ISBLK
1204         else if(S_ISBLK(mode))
1205                 return UNIX_TYPE_BLKDEV;
1206 #endif
1207 #ifdef S_ISFIFO
1208         else if(S_ISFIFO(mode))
1209                 return UNIX_TYPE_FIFO;
1210 #endif
1211 #ifdef S_ISSOCK
1212         else if(S_ISSOCK(mode))
1213                 return UNIX_TYPE_SOCKET;
1214 #endif
1215
1216         DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1217         return UNIX_TYPE_UNKNOWN;
1218 }
1219
1220 /****************************************************************************
1221  Map wire perms onto standard UNIX permissions. Obey share restrictions.
1222 ****************************************************************************/
1223
1224 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1225
1226 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1227                                 const SMB_STRUCT_STAT *psbuf,
1228                                 uint32 perms,
1229                                 enum perm_type ptype,
1230                                 mode_t *ret_perms)
1231 {
1232         mode_t ret = 0;
1233
1234         if (perms == SMB_MODE_NO_CHANGE) {
1235                 if (!VALID_STAT(*psbuf)) {
1236                         return NT_STATUS_INVALID_PARAMETER;
1237                 } else {
1238                         *ret_perms = psbuf->st_ex_mode;
1239                         return NT_STATUS_OK;
1240                 }
1241         }
1242
1243         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1244         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1245         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1246         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1247         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1248         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1249         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1250         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1251         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1252 #ifdef S_ISVTX
1253         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1254 #endif
1255 #ifdef S_ISGID
1256         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1257 #endif
1258 #ifdef S_ISUID
1259         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1260 #endif
1261
1262         switch (ptype) {
1263         case PERM_NEW_FILE:
1264                 /* Apply mode mask */
1265                 ret &= lp_create_mask(SNUM(conn));
1266                 /* Add in force bits */
1267                 ret |= lp_force_create_mode(SNUM(conn));
1268                 break;
1269         case PERM_NEW_DIR:
1270                 ret &= lp_dir_mask(SNUM(conn));
1271                 /* Add in force bits */
1272                 ret |= lp_force_dir_mode(SNUM(conn));
1273                 break;
1274         case PERM_EXISTING_FILE:
1275                 /* Apply mode mask */
1276                 ret &= lp_security_mask(SNUM(conn));
1277                 /* Add in force bits */
1278                 ret |= lp_force_security_mode(SNUM(conn));
1279                 break;
1280         case PERM_EXISTING_DIR:
1281                 /* Apply mode mask */
1282                 ret &= lp_dir_security_mask(SNUM(conn));
1283                 /* Add in force bits */
1284                 ret |= lp_force_dir_security_mode(SNUM(conn));
1285                 break;
1286         }
1287
1288         *ret_perms = ret;
1289         return NT_STATUS_OK;
1290 }
1291
1292 /****************************************************************************
1293  Needed to show the msdfs symlinks as directories. Modifies psbuf
1294  to be a directory if it's a msdfs link.
1295 ****************************************************************************/
1296
1297 static bool check_msdfs_link(connection_struct *conn,
1298                                 const char *pathname,
1299                                 SMB_STRUCT_STAT *psbuf)
1300 {
1301         int saved_errno = errno;
1302         if(lp_host_msdfs() &&
1303                 lp_msdfs_root(SNUM(conn)) &&
1304                 is_msdfs_link(conn, pathname, psbuf)) {
1305
1306                 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1307                         "as a directory\n",
1308                         pathname));
1309                 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1310                 errno = saved_errno;
1311                 return true;
1312         }
1313         errno = saved_errno;
1314         return false;
1315 }
1316
1317
1318 /****************************************************************************
1319  Get a level dependent lanman2 dir entry.
1320 ****************************************************************************/
1321
1322 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1323                                 connection_struct *conn,
1324                                 uint16 flags2,
1325                                 const char *path_mask,
1326                                 uint32 dirtype,
1327                                 int info_level,
1328                                 int requires_resume_key,
1329                                 bool dont_descend,
1330                                 bool ask_sharemode,
1331                                 char **ppdata,
1332                                 char *base_data,
1333                                 char *end_data,
1334                                 int space_remaining,
1335                                 bool *out_of_space,
1336                                 bool *got_exact_match,
1337                                 int *last_entry_off,
1338                                 struct ea_list *name_list)
1339 {
1340         char *dname;
1341         bool found = False;
1342         SMB_STRUCT_STAT sbuf;
1343         const char *mask = NULL;
1344         char *pathreal = NULL;
1345         char *fname = NULL;
1346         char *p, *q, *pdata = *ppdata;
1347         uint32 reskey=0;
1348         long prev_dirpos=0;
1349         uint32 mode=0;
1350         SMB_OFF_T file_size = 0;
1351         uint64_t allocation_size = 0;
1352         uint32 len;
1353         struct timespec mdate_ts, adate_ts, create_date_ts;
1354         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1355         char *nameptr;
1356         char *last_entry_ptr;
1357         bool was_8_3;
1358         uint32 nt_extmode; /* Used for NT connections instead of mode */
1359         bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1360         bool check_mangled_names = lp_manglednames(conn->params);
1361         char mangled_name[13]; /* mangled 8.3 name. */
1362
1363         *out_of_space = False;
1364         *got_exact_match = False;
1365
1366         ZERO_STRUCT(mdate_ts);
1367         ZERO_STRUCT(adate_ts);
1368         ZERO_STRUCT(create_date_ts);
1369
1370         if (!conn->dirptr) {
1371                 return(False);
1372         }
1373
1374         p = strrchr_m(path_mask,'/');
1375         if(p != NULL) {
1376                 if(p[1] == '\0') {
1377                         mask = talloc_strdup(ctx,"*.*");
1378                 } else {
1379                         mask = p+1;
1380                 }
1381         } else {
1382                 mask = path_mask;
1383         }
1384
1385         while (!found) {
1386                 bool got_match;
1387                 bool ms_dfs_link = False;
1388
1389                 /* Needed if we run out of space */
1390                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1391                 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1392
1393                 /*
1394                  * Due to bugs in NT client redirectors we are not using
1395                  * resume keys any more - set them to zero.
1396                  * Check out the related comments in findfirst/findnext.
1397                  * JRA.
1398                  */
1399
1400                 reskey = 0;
1401
1402                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1403                         (long)conn->dirptr,curr_dirpos));
1404
1405                 if (!dname) {
1406                         return(False);
1407                 }
1408
1409                 /*
1410                  * fname may get mangled, dname is never mangled.
1411                  * Whenever we're accessing the filesystem we use
1412                  * pathreal which is composed from dname.
1413                  */
1414
1415                 pathreal = NULL;
1416                 fname = dname;
1417
1418                 /* Mangle fname if it's an illegal name. */
1419                 if (mangle_must_mangle(dname,conn->params)) {
1420                         if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1421                                 TALLOC_FREE(fname);
1422                                 continue; /* Error - couldn't mangle. */
1423                         }
1424                         fname = talloc_strdup(ctx, mangled_name);
1425                         if (!fname) {
1426                                 return False;
1427                         }
1428                 }
1429
1430                 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1431                         got_match = mask_match(fname, mask, conn->case_sensitive);
1432                 }
1433
1434                 if(!got_match && check_mangled_names &&
1435                    !mangle_is_8_3(fname, False, conn->params)) {
1436                         /*
1437                          * It turns out that NT matches wildcards against
1438                          * both long *and* short names. This may explain some
1439                          * of the wildcard wierdness from old DOS clients
1440                          * that some people have been seeing.... JRA.
1441                          */
1442                         /* Force the mangling into 8.3. */
1443                         if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1444                                 TALLOC_FREE(fname);
1445                                 continue; /* Error - couldn't mangle. */
1446                         }
1447
1448                         if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1449                                 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1450                         }
1451                 }
1452
1453                 if (got_match) {
1454                         bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1455                         struct smb_filename *smb_fname = NULL;
1456                         NTSTATUS status;
1457
1458                         if (dont_descend && !isdots) {
1459                                 TALLOC_FREE(fname);
1460                                 continue;
1461                         }
1462
1463                         if (needslash) {
1464                                 pathreal = NULL;
1465                                 pathreal = talloc_asprintf(ctx,
1466                                         "%s/%s",
1467                                         conn->dirpath,
1468                                         dname);
1469                         } else {
1470                                 pathreal = talloc_asprintf(ctx,
1471                                         "%s%s",
1472                                         conn->dirpath,
1473                                         dname);
1474                         }
1475
1476                         if (!pathreal) {
1477                                 TALLOC_FREE(fname);
1478                                 return False;
1479                         }
1480
1481                         /* A dirent from dptr_ReadDirName isn't a stream. */
1482                         status = create_synthetic_smb_fname(ctx, pathreal,
1483                                                             NULL, &sbuf,
1484                                                             &smb_fname);
1485                         if (!NT_STATUS_IS_OK(status)) {
1486                                 TALLOC_FREE(fname);
1487                                 return false;
1488                         }
1489
1490                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1491                                 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1492                                         DEBUG(5,("get_lanman2_dir_entry: "
1493                                                  "Couldn't lstat [%s] (%s)\n",
1494                                                  smb_fname_str_dbg(smb_fname),
1495                                                  strerror(errno)));
1496                                         TALLOC_FREE(smb_fname);
1497                                         TALLOC_FREE(pathreal);
1498                                         TALLOC_FREE(fname);
1499                                         continue;
1500                                 }
1501                         } else if (!VALID_STAT(smb_fname->st) &&
1502                                    SMB_VFS_STAT(conn, smb_fname) != 0) {
1503                                 /* Needed to show the msdfs symlinks as
1504                                  * directories */
1505
1506                                 ms_dfs_link =
1507                                     check_msdfs_link(conn,
1508                                                      smb_fname->base_name,
1509                                                      &smb_fname->st);
1510                                 if (!ms_dfs_link) {
1511                                         DEBUG(5,("get_lanman2_dir_entry: "
1512                                                  "Couldn't stat [%s] (%s)\n",
1513                                                  smb_fname_str_dbg(smb_fname),
1514                                                  strerror(errno)));
1515                                         TALLOC_FREE(smb_fname);
1516                                         TALLOC_FREE(pathreal);
1517                                         TALLOC_FREE(fname);
1518                                         continue;
1519                                 }
1520                         }
1521
1522                         if (ms_dfs_link) {
1523                                 mode = dos_mode_msdfs(conn, smb_fname);
1524                         } else {
1525                                 mode = dos_mode(conn, smb_fname);
1526                         }
1527
1528                         if (!dir_check_ftype(conn,mode,dirtype)) {
1529                                 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1530                                 TALLOC_FREE(smb_fname);
1531                                 TALLOC_FREE(pathreal);
1532                                 TALLOC_FREE(fname);
1533                                 continue;
1534                         }
1535
1536                         if (!(mode & aDIR)) {
1537                                 file_size = get_file_size_stat(&smb_fname->st);
1538                         }
1539                         allocation_size =
1540                             SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1541
1542                         if (ask_sharemode) {
1543                                 struct timespec write_time_ts;
1544                                 struct file_id fileid;
1545
1546                                 ZERO_STRUCT(write_time_ts);
1547                                 fileid = vfs_file_id_from_sbuf(conn,
1548                                                                &smb_fname->st);
1549                                 get_file_infos(fileid, NULL, &write_time_ts);
1550                                 if (!null_timespec(write_time_ts)) {
1551                                         update_stat_ex_mtime(&smb_fname->st,
1552                                                              write_time_ts);
1553                                 }
1554                         }
1555
1556                         mdate_ts = smb_fname->st.st_ex_mtime;
1557                         adate_ts = smb_fname->st.st_ex_atime;
1558                         create_date_ts = smb_fname->st.st_ex_btime;
1559
1560                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1561                                 dos_filetime_timespec(&create_date_ts);
1562                                 dos_filetime_timespec(&mdate_ts);
1563                                 dos_filetime_timespec(&adate_ts);
1564                         }
1565
1566                         create_date = convert_timespec_to_time_t(create_date_ts);
1567                         mdate = convert_timespec_to_time_t(mdate_ts);
1568                         adate = convert_timespec_to_time_t(adate_ts);
1569
1570                         DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1571                                  smb_fname_str_dbg(smb_fname), fname));
1572
1573                         found = True;
1574
1575                         dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1576                         sbuf = smb_fname->st;
1577
1578                         TALLOC_FREE(smb_fname);
1579                 }
1580
1581                 if (!found)
1582                         TALLOC_FREE(fname);
1583         }
1584
1585         p = pdata;
1586         last_entry_ptr = p;
1587
1588         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1589
1590         switch (info_level) {
1591                 case SMB_FIND_INFO_STANDARD:
1592                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1593                         if(requires_resume_key) {
1594                                 SIVAL(p,0,reskey);
1595                                 p += 4;
1596                         }
1597                         srv_put_dos_date2(p,0,create_date);
1598                         srv_put_dos_date2(p,4,adate);
1599                         srv_put_dos_date2(p,8,mdate);
1600                         SIVAL(p,12,(uint32)file_size);
1601                         SIVAL(p,16,(uint32)allocation_size);
1602                         SSVAL(p,20,mode);
1603                         p += 23;
1604                         nameptr = p;
1605                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1606                                 p += ucs2_align(base_data, p, 0);
1607                         }
1608                         len = srvstr_push(base_data, flags2, p,
1609                                           fname, PTR_DIFF(end_data, p),
1610                                           STR_TERMINATE);
1611                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1612                                 if (len > 2) {
1613                                         SCVAL(nameptr, -1, len - 2);
1614                                 } else {
1615                                         SCVAL(nameptr, -1, 0);
1616                                 }
1617                         } else {
1618                                 if (len > 1) {
1619                                         SCVAL(nameptr, -1, len - 1);
1620                                 } else {
1621                                         SCVAL(nameptr, -1, 0);
1622                                 }
1623                         }
1624                         p += len;
1625                         break;
1626
1627                 case SMB_FIND_EA_SIZE:
1628                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1629                         if(requires_resume_key) {
1630                                 SIVAL(p,0,reskey);
1631                                 p += 4;
1632                         }
1633                         srv_put_dos_date2(p,0,create_date);
1634                         srv_put_dos_date2(p,4,adate);
1635                         srv_put_dos_date2(p,8,mdate);
1636                         SIVAL(p,12,(uint32)file_size);
1637                         SIVAL(p,16,(uint32)allocation_size);
1638                         SSVAL(p,20,mode);
1639                         {
1640                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1641                                 SIVAL(p,22,ea_size); /* Extended attributes */
1642                         }
1643                         p += 27;
1644                         nameptr = p - 1;
1645                         len = srvstr_push(base_data, flags2,
1646                                           p, fname, PTR_DIFF(end_data, p),
1647                                           STR_TERMINATE | STR_NOALIGN);
1648                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1649                                 if (len > 2) {
1650                                         len -= 2;
1651                                 } else {
1652                                         len = 0;
1653                                 }
1654                         } else {
1655                                 if (len > 1) {
1656                                         len -= 1;
1657                                 } else {
1658                                         len = 0;
1659                                 }
1660                         }
1661                         SCVAL(nameptr,0,len);
1662                         p += len;
1663                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1664                         break;
1665
1666                 case SMB_FIND_EA_LIST:
1667                 {
1668                         struct ea_list *file_list = NULL;
1669                         size_t ea_len = 0;
1670
1671                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1672                         if (!name_list) {
1673                                 return False;
1674                         }
1675                         if(requires_resume_key) {
1676                                 SIVAL(p,0,reskey);
1677                                 p += 4;
1678                         }
1679                         srv_put_dos_date2(p,0,create_date);
1680                         srv_put_dos_date2(p,4,adate);
1681                         srv_put_dos_date2(p,8,mdate);
1682                         SIVAL(p,12,(uint32)file_size);
1683                         SIVAL(p,16,(uint32)allocation_size);
1684                         SSVAL(p,20,mode);
1685                         p += 22; /* p now points to the EA area. */
1686
1687                         file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1688                         name_list = ea_list_union(name_list, file_list, &ea_len);
1689
1690                         /* We need to determine if this entry will fit in the space available. */
1691                         /* Max string size is 255 bytes. */
1692                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1693                                 /* Move the dirptr back to prev_dirpos */
1694                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1695                                 *out_of_space = True;
1696                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1697                                 return False; /* Not finished - just out of space */
1698                         }
1699
1700                         /* Push the ea_data followed by the name. */
1701                         p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1702                         nameptr = p;
1703                         len = srvstr_push(base_data, flags2,
1704                                           p + 1, fname, PTR_DIFF(end_data, p+1),
1705                                           STR_TERMINATE | STR_NOALIGN);
1706                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1707                                 if (len > 2) {
1708                                         len -= 2;
1709                                 } else {
1710                                         len = 0;
1711                                 }
1712                         } else {
1713                                 if (len > 1) {
1714                                         len -= 1;
1715                                 } else {
1716                                         len = 0;
1717                                 }
1718                         }
1719                         SCVAL(nameptr,0,len);
1720                         p += len + 1;
1721                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1722                         break;
1723                 }
1724
1725                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1726                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1728                         p += 4;
1729                         SIVAL(p,0,reskey); p += 4;
1730                         put_long_date_timespec(p,create_date_ts); p += 8;
1731                         put_long_date_timespec(p,adate_ts); p += 8;
1732                         put_long_date_timespec(p,mdate_ts); p += 8;
1733                         put_long_date_timespec(p,mdate_ts); p += 8;
1734                         SOFF_T(p,0,file_size); p += 8;
1735                         SOFF_T(p,0,allocation_size); p += 8;
1736                         SIVAL(p,0,nt_extmode); p += 4;
1737                         q = p; p += 4; /* q is placeholder for name length. */
1738                         {
1739                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1740                                 SIVAL(p,0,ea_size); /* Extended attributes */
1741                                 p += 4;
1742                         }
1743                         /* Clear the short name buffer. This is
1744                          * IMPORTANT as not doing so will trigger
1745                          * a Win2k client bug. JRA.
1746                          */
1747                         if (!was_8_3 && check_mangled_names) {
1748                                 if (!name_to_8_3(fname,mangled_name,True,
1749                                                    conn->params)) {
1750                                         /* Error - mangle failed ! */
1751                                         memset(mangled_name,'\0',12);
1752                                 }
1753                                 mangled_name[12] = 0;
1754                                 len = srvstr_push(base_data, flags2,
1755                                                   p+2, mangled_name, 24,
1756                                                   STR_UPPER|STR_UNICODE);
1757                                 if (len < 24) {
1758                                         memset(p + 2 + len,'\0',24 - len);
1759                                 }
1760                                 SSVAL(p, 0, len);
1761                         } else {
1762                                 memset(p,'\0',26);
1763                         }
1764                         p += 2 + 24;
1765                         len = srvstr_push(base_data, flags2, p,
1766                                           fname, PTR_DIFF(end_data, p),
1767                                           STR_TERMINATE_ASCII);
1768                         SIVAL(q,0,len);
1769                         p += len;
1770                         SIVAL(p,0,0); /* Ensure any padding is null. */
1771                         len = PTR_DIFF(p, pdata);
1772                         len = (len + 3) & ~3;
1773                         SIVAL(pdata,0,len);
1774                         p = pdata + len;
1775                         break;
1776
1777                 case SMB_FIND_FILE_DIRECTORY_INFO:
1778                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1779                         p += 4;
1780                         SIVAL(p,0,reskey); p += 4;
1781                         put_long_date_timespec(p,create_date_ts); p += 8;
1782                         put_long_date_timespec(p,adate_ts); p += 8;
1783                         put_long_date_timespec(p,mdate_ts); p += 8;
1784                         put_long_date_timespec(p,mdate_ts); p += 8;
1785                         SOFF_T(p,0,file_size); p += 8;
1786                         SOFF_T(p,0,allocation_size); p += 8;
1787                         SIVAL(p,0,nt_extmode); p += 4;
1788                         len = srvstr_push(base_data, flags2,
1789                                           p + 4, fname, PTR_DIFF(end_data, p+4),
1790                                           STR_TERMINATE_ASCII);
1791                         SIVAL(p,0,len);
1792                         p += 4 + len;
1793                         SIVAL(p,0,0); /* Ensure any padding is null. */
1794                         len = PTR_DIFF(p, pdata);
1795                         len = (len + 3) & ~3;
1796                         SIVAL(pdata,0,len);
1797                         p = pdata + len;
1798                         break;
1799
1800                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1801                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1802                         p += 4;
1803                         SIVAL(p,0,reskey); p += 4;
1804                         put_long_date_timespec(p,create_date_ts); p += 8;
1805                         put_long_date_timespec(p,adate_ts); p += 8;
1806                         put_long_date_timespec(p,mdate_ts); p += 8;
1807                         put_long_date_timespec(p,mdate_ts); p += 8;
1808                         SOFF_T(p,0,file_size); p += 8;
1809                         SOFF_T(p,0,allocation_size); p += 8;
1810                         SIVAL(p,0,nt_extmode); p += 4;
1811                         q = p; p += 4; /* q is placeholder for name length. */
1812                         {
1813                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1814                                 SIVAL(p,0,ea_size); /* Extended attributes */
1815                                 p +=4;
1816                         }
1817                         len = srvstr_push(base_data, flags2, p,
1818                                           fname, PTR_DIFF(end_data, p),
1819                                           STR_TERMINATE_ASCII);
1820                         SIVAL(q, 0, len);
1821                         p += len;
1822
1823                         SIVAL(p,0,0); /* Ensure any padding is null. */
1824                         len = PTR_DIFF(p, pdata);
1825                         len = (len + 3) & ~3;
1826                         SIVAL(pdata,0,len);
1827                         p = pdata + len;
1828                         break;
1829
1830                 case SMB_FIND_FILE_NAMES_INFO:
1831                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1832                         p += 4;
1833                         SIVAL(p,0,reskey); p += 4;
1834                         p += 4;
1835                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1836                            acl on a dir (tridge) */
1837                         len = srvstr_push(base_data, flags2, p,
1838                                           fname, PTR_DIFF(end_data, p),
1839                                           STR_TERMINATE_ASCII);
1840                         SIVAL(p, -4, len);
1841                         p += len;
1842                         SIVAL(p,0,0); /* Ensure any padding is null. */
1843                         len = PTR_DIFF(p, pdata);
1844                         len = (len + 3) & ~3;
1845                         SIVAL(pdata,0,len);
1846                         p = pdata + len;
1847                         break;
1848
1849                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1850                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1851                         p += 4;
1852                         SIVAL(p,0,reskey); p += 4;
1853                         put_long_date_timespec(p,create_date_ts); p += 8;
1854                         put_long_date_timespec(p,adate_ts); p += 8;
1855                         put_long_date_timespec(p,mdate_ts); p += 8;
1856                         put_long_date_timespec(p,mdate_ts); p += 8;
1857                         SOFF_T(p,0,file_size); p += 8;
1858                         SOFF_T(p,0,allocation_size); p += 8;
1859                         SIVAL(p,0,nt_extmode); p += 4;
1860                         q = p; p += 4; /* q is placeholder for name length. */
1861                         {
1862                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1863                                 SIVAL(p,0,ea_size); /* Extended attributes */
1864                                 p +=4;
1865                         }
1866                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1867                         SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1868                         SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1869                         len = srvstr_push(base_data, flags2, p,
1870                                           fname, PTR_DIFF(end_data, p),
1871                                           STR_TERMINATE_ASCII);
1872                         SIVAL(q, 0, len);
1873                         p += len; 
1874                         SIVAL(p,0,0); /* Ensure any padding is null. */
1875                         len = PTR_DIFF(p, pdata);
1876                         len = (len + 3) & ~3;
1877                         SIVAL(pdata,0,len);
1878                         p = pdata + len;
1879                         break;
1880
1881                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1882                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1883                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1884                         p += 4;
1885                         SIVAL(p,0,reskey); p += 4;
1886                         put_long_date_timespec(p,create_date_ts); p += 8;
1887                         put_long_date_timespec(p,adate_ts); p += 8;
1888                         put_long_date_timespec(p,mdate_ts); p += 8;
1889                         put_long_date_timespec(p,mdate_ts); p += 8;
1890                         SOFF_T(p,0,file_size); p += 8;
1891                         SOFF_T(p,0,allocation_size); p += 8;
1892                         SIVAL(p,0,nt_extmode); p += 4;
1893                         q = p; p += 4; /* q is placeholder for name length */
1894                         {
1895                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1896                                 SIVAL(p,0,ea_size); /* Extended attributes */
1897                                 p +=4;
1898                         }
1899                         /* Clear the short name buffer. This is
1900                          * IMPORTANT as not doing so will trigger
1901                          * a Win2k client bug. JRA.
1902                          */
1903                         if (!was_8_3 && check_mangled_names) {
1904                                 if (!name_to_8_3(fname,mangled_name,True,
1905                                                 conn->params)) {
1906                                         /* Error - mangle failed ! */
1907                                         memset(mangled_name,'\0',12);
1908                                 }
1909                                 mangled_name[12] = 0;
1910                                 len = srvstr_push(base_data, flags2,
1911                                                   p+2, mangled_name, 24,
1912                                                   STR_UPPER|STR_UNICODE);
1913                                 SSVAL(p, 0, len);
1914                                 if (len < 24) {
1915                                         memset(p + 2 + len,'\0',24 - len);
1916                                 }
1917                                 SSVAL(p, 0, len);
1918                         } else {
1919                                 memset(p,'\0',26);
1920                         }
1921                         p += 26;
1922                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1923                         SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1924                         SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1925                         len = srvstr_push(base_data, flags2, p,
1926                                           fname, PTR_DIFF(end_data, p),
1927                                           STR_TERMINATE_ASCII);
1928                         SIVAL(q,0,len);
1929                         p += len;
1930                         SIVAL(p,0,0); /* Ensure any padding is null. */
1931                         len = PTR_DIFF(p, pdata);
1932                         len = (len + 3) & ~3;
1933                         SIVAL(pdata,0,len);
1934                         p = pdata + len;
1935                         break;
1936
1937                 /* CIFS UNIX Extension. */
1938
1939                 case SMB_FIND_FILE_UNIX:
1940                 case SMB_FIND_FILE_UNIX_INFO2:
1941                         p+= 4;
1942                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1943
1944                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1945
1946                         if (info_level == SMB_FIND_FILE_UNIX) {
1947                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1948                                 p = store_file_unix_basic(conn, p,
1949                                                         NULL, &sbuf);
1950                                 len = srvstr_push(base_data, flags2, p,
1951                                                   fname, PTR_DIFF(end_data, p),
1952                                                   STR_TERMINATE);
1953                         } else {
1954                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1955                                 p = store_file_unix_basic_info2(conn, p,
1956                                                         NULL, &sbuf);
1957                                 nameptr = p;
1958                                 p += 4;
1959                                 len = srvstr_push(base_data, flags2, p, fname,
1960                                                   PTR_DIFF(end_data, p), 0);
1961                                 SIVAL(nameptr, 0, len);
1962                         }
1963
1964                         p += len;
1965                         SIVAL(p,0,0); /* Ensure any padding is null. */
1966
1967                         len = PTR_DIFF(p, pdata);
1968                         len = (len + 3) & ~3;
1969                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1970                         p = pdata + len;
1971                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1972
1973                         break;
1974
1975                 default:
1976                         TALLOC_FREE(fname);
1977                         return(False);
1978         }
1979
1980         TALLOC_FREE(fname);
1981         if (PTR_DIFF(p,pdata) > space_remaining) {
1982                 /* Move the dirptr back to prev_dirpos */
1983                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1984                 *out_of_space = True;
1985                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1986                 return False; /* Not finished - just out of space */
1987         }
1988
1989         /* Setup the last entry pointer, as an offset from base_data */
1990         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1991         /* Advance the data pointer to the next slot */
1992         *ppdata = p;
1993
1994         return(found);
1995 }
1996
1997 /****************************************************************************
1998  Reply to a TRANS2_FINDFIRST.
1999 ****************************************************************************/
2000
2001 static void call_trans2findfirst(connection_struct *conn,
2002                                  struct smb_request *req,
2003                                  char **pparams, int total_params,
2004                                  char **ppdata, int total_data,
2005                                  unsigned int max_data_bytes)
2006 {
2007         /* We must be careful here that we don't return more than the
2008                 allowed number of data bytes. If this means returning fewer than
2009                 maxentries then so be it. We assume that the redirector has
2010                 enough room for the fixed number of parameter bytes it has
2011                 requested. */
2012         struct smb_filename *smb_dname = NULL;
2013         char *params = *pparams;
2014         char *pdata = *ppdata;
2015         char *data_end;
2016         uint32 dirtype;
2017         int maxentries;
2018         uint16 findfirst_flags;
2019         bool close_after_first;
2020         bool close_if_end;
2021         bool requires_resume_key;
2022         int info_level;
2023         char *directory = NULL;
2024         char *mask = NULL;
2025         char *p;
2026         int last_entry_off=0;
2027         int dptr_num = -1;
2028         int numentries = 0;
2029         int i;
2030         bool finished = False;
2031         bool dont_descend = False;
2032         bool out_of_space = False;
2033         int space_remaining;
2034         bool mask_contains_wcard = False;
2035         struct ea_list *ea_list = NULL;
2036         NTSTATUS ntstatus = NT_STATUS_OK;
2037         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2038         TALLOC_CTX *ctx = talloc_tos();
2039
2040         if (total_params < 13) {
2041                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2042                 return;
2043         }
2044
2045         dirtype = SVAL(params,0);
2046         maxentries = SVAL(params,2);
2047         findfirst_flags = SVAL(params,4);
2048         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2049         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2050         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2051         info_level = SVAL(params,6);
2052
2053         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2054 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2055                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2056                 info_level, max_data_bytes));
2057
2058         if (!maxentries) {
2059                 /* W2K3 seems to treat zero as 1. */
2060                 maxentries = 1;
2061         }
2062
2063         switch (info_level) {
2064                 case SMB_FIND_INFO_STANDARD:
2065                 case SMB_FIND_EA_SIZE:
2066                 case SMB_FIND_EA_LIST:
2067                 case SMB_FIND_FILE_DIRECTORY_INFO:
2068                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2069                 case SMB_FIND_FILE_NAMES_INFO:
2070                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2071                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2072                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2073                         break;
2074                 case SMB_FIND_FILE_UNIX:
2075                 case SMB_FIND_FILE_UNIX_INFO2:
2076                         /* Always use filesystem for UNIX mtime query. */
2077                         ask_sharemode = false;
2078                         if (!lp_unix_extensions()) {
2079                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2080                                 return;
2081                         }
2082                         break;
2083                 default:
2084                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2085                         return;
2086         }
2087
2088         srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2089                               params+12, total_params - 12,
2090                               STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2091         if (!NT_STATUS_IS_OK(ntstatus)) {
2092                 reply_nterror(req, ntstatus);
2093                 return;
2094         }
2095
2096         ntstatus = resolve_dfspath_wcard(ctx, conn,
2097                         req->flags2 & FLAGS2_DFS_PATHNAMES,
2098                         directory,
2099                         &directory,
2100                         &mask_contains_wcard);
2101         if (!NT_STATUS_IS_OK(ntstatus)) {
2102                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2103                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2104                                         ERRSRV, ERRbadpath);
2105                         return;
2106                 }
2107                 reply_nterror(req, ntstatus);
2108                 return;
2109         }
2110
2111         ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2112                                 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2113         if (!NT_STATUS_IS_OK(ntstatus)) {
2114                 reply_nterror(req, ntstatus);
2115                 return;
2116         }
2117
2118         mask = smb_dname->original_lcomp;
2119
2120         ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2121         TALLOC_FREE(smb_dname);
2122         if (!NT_STATUS_IS_OK(ntstatus)) {
2123                 reply_nterror(req, ntstatus);
2124                 return;
2125         }
2126
2127         ntstatus = check_name(conn, directory);
2128         if (!NT_STATUS_IS_OK(ntstatus)) {
2129                 reply_nterror(req, ntstatus);
2130                 return;
2131         }
2132
2133         p = strrchr_m(directory,'/');
2134         if(p == NULL) {
2135                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2136                 if((directory[0] == '.') && (directory[1] == '\0')) {
2137                         mask = talloc_strdup(ctx,"*");
2138                         if (!mask) {
2139                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2140                                 return;
2141                         }
2142                         mask_contains_wcard = True;
2143                 }
2144                 directory = talloc_strdup(talloc_tos(), "./");
2145                 if (!directory) {
2146                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2147                         return;
2148                 }
2149         } else {
2150                 *p = 0;
2151         }
2152
2153         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2154
2155         if (info_level == SMB_FIND_EA_LIST) {
2156                 uint32 ea_size;
2157
2158                 if (total_data < 4) {
2159                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2160                         return;
2161                 }
2162
2163                 ea_size = IVAL(pdata,0);
2164                 if (ea_size != total_data) {
2165                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2166 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2167                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2168                         return;
2169                 }
2170
2171                 if (!lp_ea_support(SNUM(conn))) {
2172                         reply_doserror(req, ERRDOS, ERReasnotsupported);
2173                         return;
2174                 }
2175
2176                 /* Pull out the list of names. */
2177                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2178                 if (!ea_list) {
2179                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2180                         return;
2181                 }
2182         }
2183
2184         *ppdata = (char *)SMB_REALLOC(
2185                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2186         if(*ppdata == NULL ) {
2187                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2188                 return;
2189         }
2190         pdata = *ppdata;
2191         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2192
2193         /* Realloc the params space */
2194         *pparams = (char *)SMB_REALLOC(*pparams, 10);
2195         if (*pparams == NULL) {
2196                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2197                 return;
2198         }
2199         params = *pparams;
2200
2201         /* Save the wildcard match and attribs we are using on this directory -
2202                 needed as lanman2 assumes these are being saved between calls */
2203
2204         ntstatus = dptr_create(conn,
2205                                 directory,
2206                                 False,
2207                                 True,
2208                                 req->smbpid,
2209                                 mask,
2210                                 mask_contains_wcard,
2211                                 dirtype,
2212                                 &conn->dirptr);
2213
2214         if (!NT_STATUS_IS_OK(ntstatus)) {
2215                 reply_nterror(req, ntstatus);
2216                 return;
2217         }
2218
2219         dptr_num = dptr_dnum(conn->dirptr);
2220         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2221
2222         /* Initialize per TRANS2_FIND_FIRST operation data */
2223         dptr_init_search_op(conn->dirptr);
2224
2225         /* We don't need to check for VOL here as this is returned by
2226                 a different TRANS2 call. */
2227
2228         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2229         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2230                 dont_descend = True;
2231
2232         p = pdata;
2233         space_remaining = max_data_bytes;
2234         out_of_space = False;
2235
2236         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2237                 bool got_exact_match = False;
2238
2239                 /* this is a heuristic to avoid seeking the dirptr except when
2240                         absolutely necessary. It allows for a filename of about 40 chars */
2241                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2242                         out_of_space = True;
2243                         finished = False;
2244                 } else {
2245                         finished = !get_lanman2_dir_entry(ctx,
2246                                         conn,
2247                                         req->flags2,
2248                                         mask,dirtype,info_level,
2249                                         requires_resume_key,dont_descend,
2250                                         ask_sharemode,
2251                                         &p,pdata,data_end,
2252                                         space_remaining, &out_of_space,
2253                                         &got_exact_match,
2254                                         &last_entry_off, ea_list);
2255                 }
2256
2257                 if (finished && out_of_space)
2258                         finished = False;
2259
2260                 if (!finished && !out_of_space)
2261                         numentries++;
2262
2263                 /*
2264                  * As an optimisation if we know we aren't looking
2265                  * for a wildcard name (ie. the name matches the wildcard exactly)
2266                  * then we can finish on any (first) match.
2267                  * This speeds up large directory searches. JRA.
2268                  */
2269
2270                 if(got_exact_match)
2271                         finished = True;
2272
2273                 /* Ensure space_remaining never goes -ve. */
2274                 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2275                         space_remaining = 0;
2276                         out_of_space = true;
2277                 } else {
2278                         space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2279                 }
2280         }
2281
2282         /* Check if we can close the dirptr */
2283         if(close_after_first || (finished && close_if_end)) {
2284                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2285                 dptr_close(&dptr_num);
2286         }
2287
2288         /*
2289          * If there are no matching entries we must return ERRDOS/ERRbadfile -
2290          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2291          * the protocol level is less than NT1. Tested with smbclient. JRA.
2292          * This should fix the OS/2 client bug #2335.
2293          */
2294
2295         if(numentries == 0) {
2296                 dptr_close(&dptr_num);
2297                 if (Protocol < PROTOCOL_NT1) {
2298                         reply_doserror(req, ERRDOS, ERRnofiles);
2299                         return;
2300                 } else {
2301                         reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2302                                         ERRDOS, ERRbadfile);
2303                         return;
2304                 }
2305         }
2306
2307         /* At this point pdata points to numentries directory entries. */
2308
2309         /* Set up the return parameter block */
2310         SSVAL(params,0,dptr_num);
2311         SSVAL(params,2,numentries);
2312         SSVAL(params,4,finished);
2313         SSVAL(params,6,0); /* Never an EA error */
2314         SSVAL(params,8,last_entry_off);
2315
2316         send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2317                             max_data_bytes);
2318
2319         if ((! *directory) && dptr_path(dptr_num)) {
2320                 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2321                 if (!directory) {
2322                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2323                 }
2324         }
2325
2326         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2327                 smb_fn_name(req->cmd),
2328                 mask, directory, dirtype, numentries ) );
2329
2330         /*
2331          * Force a name mangle here to ensure that the
2332          * mask as an 8.3 name is top of the mangled cache.
2333          * The reasons for this are subtle. Don't remove
2334          * this code unless you know what you are doing
2335          * (see PR#13758). JRA.
2336          */
2337
2338         if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2339                 char mangled_name[13];
2340                 name_to_8_3(mask, mangled_name, True, conn->params);
2341         }
2342
2343         return;
2344 }
2345
2346 /****************************************************************************
2347  Reply to a TRANS2_FINDNEXT.
2348 ****************************************************************************/
2349
2350 static void call_trans2findnext(connection_struct *conn,
2351                                 struct smb_request *req,
2352                                 char **pparams, int total_params,
2353                                 char **ppdata, int total_data,
2354                                 unsigned int max_data_bytes)
2355 {
2356         /* We must be careful here that we don't return more than the
2357                 allowed number of data bytes. If this means returning fewer than
2358                 maxentries then so be it. We assume that the redirector has
2359                 enough room for the fixed number of parameter bytes it has
2360                 requested. */
2361         char *params = *pparams;
2362         char *pdata = *ppdata;
2363         char *data_end;
2364         int dptr_num;
2365         int maxentries;
2366         uint16 info_level;
2367         uint32 resume_key;
2368         uint16 findnext_flags;
2369         bool close_after_request;
2370         bool close_if_end;
2371         bool requires_resume_key;
2372         bool continue_bit;
2373         bool mask_contains_wcard = False;
2374         char *resume_name = NULL;
2375         const char *mask = NULL;
2376         const char *directory = NULL;
2377         char *p = NULL;
2378         uint16 dirtype;
2379         int numentries = 0;
2380         int i, last_entry_off=0;
2381         bool finished = False;
2382         bool dont_descend = False;
2383         bool out_of_space = False;
2384         int space_remaining;
2385         struct ea_list *ea_list = NULL;
2386         NTSTATUS ntstatus = NT_STATUS_OK;
2387         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2388         TALLOC_CTX *ctx = talloc_tos();
2389
2390         if (total_params < 13) {
2391                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2392                 return;
2393         }
2394
2395         dptr_num = SVAL(params,0);
2396         maxentries = SVAL(params,2);
2397         info_level = SVAL(params,4);
2398         resume_key = IVAL(params,6);
2399         findnext_flags = SVAL(params,10);
2400         close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2401         close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2402         requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2403         continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2404
2405         srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2406                               params+12,
2407                               total_params - 12, STR_TERMINATE, &ntstatus,
2408                               &mask_contains_wcard);
2409         if (!NT_STATUS_IS_OK(ntstatus)) {
2410                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2411                    complain (it thinks we're asking for the directory above the shared
2412                    path or an invalid name). Catch this as the resume name is only compared, never used in
2413                    a file access. JRA. */
2414                 srvstr_pull_talloc(ctx, params, req->flags2,
2415                                 &resume_name, params+12,
2416                                 total_params - 12,
2417                                 STR_TERMINATE);
2418
2419                 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2420                         reply_nterror(req, ntstatus);
2421                         return;
2422                 }
2423         }
2424
2425         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2426 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2427 resume_key = %d resume name = %s continue=%d level = %d\n",
2428                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
2429                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2430
2431         if (!maxentries) {
2432                 /* W2K3 seems to treat zero as 1. */
2433                 maxentries = 1;
2434         }
2435
2436         switch (info_level) {
2437                 case SMB_FIND_INFO_STANDARD:
2438                 case SMB_FIND_EA_SIZE:
2439                 case SMB_FIND_EA_LIST:
2440                 case SMB_FIND_FILE_DIRECTORY_INFO:
2441                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2442                 case SMB_FIND_FILE_NAMES_INFO:
2443                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2444                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2445                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2446                         break;
2447                 case SMB_FIND_FILE_UNIX:
2448                 case SMB_FIND_FILE_UNIX_INFO2:
2449                         /* Always use filesystem for UNIX mtime query. */
2450                         ask_sharemode = false;
2451                         if (!lp_unix_extensions()) {
2452                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2453                                 return;
2454                         }
2455                         break;
2456                 default:
2457                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2458                         return;
2459         }
2460
2461         if (info_level == SMB_FIND_EA_LIST) {
2462                 uint32 ea_size;
2463
2464                 if (total_data < 4) {
2465                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2466                         return;
2467                 }
2468
2469                 ea_size = IVAL(pdata,0);
2470                 if (ea_size != total_data) {
2471                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2472 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2473                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2474                         return;
2475                 }
2476
2477                 if (!lp_ea_support(SNUM(conn))) {
2478                         reply_doserror(req, ERRDOS, ERReasnotsupported);
2479                         return;
2480                 }
2481
2482                 /* Pull out the list of names. */
2483                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2484                 if (!ea_list) {
2485                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2486                         return;
2487                 }
2488         }
2489
2490         *ppdata = (char *)SMB_REALLOC(
2491                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2492         if(*ppdata == NULL) {
2493                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2494                 return;
2495         }
2496
2497         pdata = *ppdata;
2498         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2499
2500         /* Realloc the params space */
2501         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2502         if(*pparams == NULL ) {
2503                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2504                 return;
2505         }
2506
2507         params = *pparams;
2508
2509         /* Check that the dptr is valid */
2510         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2511                 reply_doserror(req, ERRDOS, ERRnofiles);
2512                 return;
2513         }
2514
2515         string_set(&conn->dirpath,dptr_path(dptr_num));
2516
2517         /* Get the wildcard mask from the dptr */
2518         if((p = dptr_wcard(dptr_num))== NULL) {
2519                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2520                 reply_doserror(req, ERRDOS, ERRnofiles);
2521                 return;
2522         }
2523
2524         mask = p;
2525         directory = conn->dirpath;
2526
2527         /* Get the attr mask from the dptr */
2528         dirtype = dptr_attr(dptr_num);
2529
2530         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2531                 dptr_num, mask, dirtype,
2532                 (long)conn->dirptr,
2533                 dptr_TellDir(conn->dirptr)));
2534
2535         /* Initialize per TRANS2_FIND_NEXT operation data */
2536         dptr_init_search_op(conn->dirptr);
2537
2538         /* We don't need to check for VOL here as this is returned by
2539                 a different TRANS2 call. */
2540
2541         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2542         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2543                 dont_descend = True;
2544
2545         p = pdata;
2546         space_remaining = max_data_bytes;
2547         out_of_space = False;
2548
2549         /*
2550          * Seek to the correct position. We no longer use the resume key but
2551          * depend on the last file name instead.
2552          */
2553
2554         if(*resume_name && !continue_bit) {
2555                 SMB_STRUCT_STAT st;
2556
2557                 long current_pos = 0;
2558                 /*
2559                  * Remember, name_to_8_3 is called by
2560                  * get_lanman2_dir_entry(), so the resume name
2561                  * could be mangled. Ensure we check the unmangled name.
2562                  */
2563
2564                 if (mangle_is_mangled(resume_name, conn->params)) {
2565                         char *new_resume_name = NULL;
2566                         mangle_lookup_name_from_8_3(ctx,
2567                                                 resume_name,
2568                                                 &new_resume_name,
2569                                                 conn->params);
2570                         if (new_resume_name) {
2571                                 resume_name = new_resume_name;
2572                         }
2573                 }
2574
2575                 /*
2576                  * Fix for NT redirector problem triggered by resume key indexes
2577                  * changing between directory scans. We now return a resume key of 0
2578                  * and instead look for the filename to continue from (also given
2579                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2580                  * findfirst/findnext (as is usual) then the directory pointer
2581                  * should already be at the correct place.
2582                  */
2583
2584                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2585         } /* end if resume_name && !continue_bit */
2586
2587         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2588                 bool got_exact_match = False;
2589
2590                 /* this is a heuristic to avoid seeking the dirptr except when 
2591                         absolutely necessary. It allows for a filename of about 40 chars */
2592                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2593                         out_of_space = True;
2594                         finished = False;
2595                 } else {
2596                         finished = !get_lanman2_dir_entry(ctx,
2597                                                 conn,
2598                                                 req->flags2,
2599                                                 mask,dirtype,info_level,
2600                                                 requires_resume_key,dont_descend,
2601                                                 ask_sharemode,
2602                                                 &p,pdata,data_end,
2603                                                 space_remaining, &out_of_space,
2604                                                 &got_exact_match,
2605                                                 &last_entry_off, ea_list);
2606                 }
2607
2608                 if (finished && out_of_space)
2609                         finished = False;
2610
2611                 if (!finished && !out_of_space)
2612                         numentries++;
2613
2614                 /*
2615                  * As an optimisation if we know we aren't looking
2616                  * for a wildcard name (ie. the name matches the wildcard exactly)
2617                  * then we can finish on any (first) match.
2618                  * This speeds up large directory searches. JRA.
2619                  */
2620
2621                 if(got_exact_match)
2622                         finished = True;
2623
2624                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2625         }
2626
2627         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2628                 smb_fn_name(req->cmd),
2629                 mask, directory, dirtype, numentries ) );
2630
2631         /* Check if we can close the dirptr */
2632         if(close_after_request || (finished && close_if_end)) {
2633                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2634                 dptr_close(&dptr_num); /* This frees up the saved mask */
2635         }
2636
2637         /* Set up the return parameter block */
2638         SSVAL(params,0,numentries);
2639         SSVAL(params,2,finished);
2640         SSVAL(params,4,0); /* Never an EA error */
2641         SSVAL(params,6,last_entry_off);
2642
2643         send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2644                             max_data_bytes);
2645
2646         return;
2647 }
2648
2649 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2650 {
2651         E_md4hash(lp_servicename(SNUM(conn)),objid);
2652         return objid;
2653 }
2654
2655 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2656 {
2657         SMB_ASSERT(extended_info != NULL);
2658
2659         extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2660         extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2661                                        | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2662                                        | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2663 #ifdef SAMBA_VERSION_REVISION
2664         extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2665 #endif
2666         extended_info->samba_subversion = 0;
2667 #ifdef SAMBA_VERSION_RC_RELEASE
2668         extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2669 #else
2670 #ifdef SAMBA_VERSION_PRE_RELEASE
2671         extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2672 #endif
2673 #endif
2674 #ifdef SAMBA_VERSION_VENDOR_PATCH
2675         extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2676 #endif
2677         extended_info->samba_gitcommitdate = 0;
2678 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2679         unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2680 #endif
2681
2682         memset(extended_info->samba_version_string, 0,
2683                sizeof(extended_info->samba_version_string));
2684
2685         snprintf (extended_info->samba_version_string,
2686                   sizeof(extended_info->samba_version_string),
2687                   "%s", samba_version_string());
2688 }
2689
2690 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2691                          TALLOC_CTX *mem_ctx,
2692                          uint16_t info_level,
2693                          SMB_STRUCT_STAT st,
2694                          uint16_t flags2,
2695                          unsigned int max_data_bytes,
2696                          char **ppdata,
2697                          int *ret_data_len)
2698 {
2699         char *pdata, *end_data;
2700         int data_len = 0, len;
2701         const char *vname = volume_label(SNUM(conn));
2702         int snum = SNUM(conn);
2703         char *fstype = lp_fstype(SNUM(conn));
2704         uint32 additional_flags = 0;
2705
2706         if (IS_IPC(conn)) {
2707                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2708                         DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2709                                 "info level (0x%x) on IPC$.\n",
2710                                 (unsigned int)info_level));
2711                         return NT_STATUS_ACCESS_DENIED;
2712                 }
2713         }
2714
2715         DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2716
2717         *ppdata = (char *)SMB_REALLOC(
2718                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2719         if (*ppdata == NULL) {
2720                 return NT_STATUS_NO_MEMORY;
2721         }
2722
2723         pdata = *ppdata;
2724         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2725         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2726
2727         switch (info_level) {
2728                 case SMB_INFO_ALLOCATION:
2729                 {
2730                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2731                         data_len = 18;
2732                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2733                                 return map_nt_error_from_unix(errno);
2734                         }
2735
2736                         block_size = lp_block_size(snum);
2737                         if (bsize < block_size) {
2738                                 uint64_t factor = block_size/bsize;
2739                                 bsize = block_size;
2740                                 dsize /= factor;
2741                                 dfree /= factor;
2742                         }
2743                         if (bsize > block_size) {
2744                                 uint64_t factor = bsize/block_size;
2745                                 bsize = block_size;
2746                                 dsize *= factor;
2747                                 dfree *= factor;
2748                         }
2749                         bytes_per_sector = 512;
2750                         sectors_per_unit = bsize/bytes_per_sector;
2751
2752                         DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2753 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2754                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2755
2756                         SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2757                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2758                         SIVAL(pdata,l1_cUnit,dsize);
2759                         SIVAL(pdata,l1_cUnitAvail,dfree);
2760                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2761                         break;
2762                 }
2763
2764                 case SMB_INFO_VOLUME:
2765                         /* Return volume name */
2766                         /* 
2767                          * Add volume serial number - hash of a combination of
2768                          * the called hostname and the service name.
2769                          */
2770                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2771                         /*
2772                          * Win2k3 and previous mess this up by sending a name length
2773                          * one byte short. I believe only older clients (OS/2 Win9x) use
2774                          * this call so try fixing this by adding a terminating null to
2775                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2776                          */
2777                         len = srvstr_push(
2778                                 pdata, flags2,
2779                                 pdata+l2_vol_szVolLabel, vname,
2780                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2781                                 STR_NOALIGN|STR_TERMINATE);
2782                         SCVAL(pdata,l2_vol_cch,len);
2783                         data_len = l2_vol_szVolLabel + len;
2784                         DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2785                                  (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2786                                  len, vname));
2787                         break;
2788
2789                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2790                 case SMB_FS_ATTRIBUTE_INFORMATION:
2791
2792                         additional_flags = 0;
2793 #if defined(HAVE_SYS_QUOTAS)
2794                         additional_flags |= FILE_VOLUME_QUOTAS;
2795 #endif
2796
2797                         if(lp_nt_acl_support(SNUM(conn))) {
2798                                 additional_flags |= FILE_PERSISTENT_ACLS;
2799                         }
2800
2801                         /* Capabilities are filled in at connection time through STATVFS call */
2802                         additional_flags |= conn->fs_capabilities;
2803
2804                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2805                                 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2806                                 additional_flags); /* FS ATTRIBUTES */
2807
2808                         SIVAL(pdata,4,255); /* Max filename component length */
2809                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2810                                 and will think we can't do long filenames */
2811                         len = srvstr_push(pdata, flags2, pdata+12, fstype,
2812                                           PTR_DIFF(end_data, pdata+12),
2813                                           STR_UNICODE);
2814                         SIVAL(pdata,8,len);
2815                         data_len = 12 + len;
2816                         break;
2817
2818                 case SMB_QUERY_FS_LABEL_INFO:
2819                 case SMB_FS_LABEL_INFORMATION:
2820                         len = srvstr_push(pdata, flags2, pdata+4, vname,
2821                                           PTR_DIFF(end_data, pdata+4), 0);
2822                         data_len = 4 + len;
2823                         SIVAL(pdata,0,len);
2824                         break;
2825
2826                 case SMB_QUERY_FS_VOLUME_INFO:      
2827                 case SMB_FS_VOLUME_INFORMATION:
2828
2829                         /* 
2830                          * Add volume serial number - hash of a combination of
2831                          * the called hostname and the service name.
2832                          */
2833                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2834                                 (str_checksum(get_local_machine_name())<<16));
2835
2836                         /* Max label len is 32 characters. */
2837                         len = srvstr_push(pdata, flags2, pdata+18, vname,
2838                                           PTR_DIFF(end_data, pdata+18),
2839                                           STR_UNICODE);
2840                         SIVAL(pdata,12,len);
2841                         data_len = 18+len;
2842
2843                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2844                                 (int)strlen(vname),vname, lp_servicename(snum)));
2845                         break;
2846
2847                 case SMB_QUERY_FS_SIZE_INFO:
2848                 case SMB_FS_SIZE_INFORMATION:
2849                 {
2850                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2851                         data_len = 24;
2852                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2853                                 return map_nt_error_from_unix(errno);
2854                         }
2855                         block_size = lp_block_size(snum);
2856                         if (bsize < block_size) {
2857                                 uint64_t factor = block_size/bsize;
2858                                 bsize = block_size;
2859                                 dsize /= factor;
2860                                 dfree /= factor;
2861                         }
2862                         if (bsize > block_size) {
2863                                 uint64_t factor = bsize/block_size;
2864                                 bsize = block_size;
2865                                 dsize *= factor;
2866                                 dfree *= factor;
2867                         }
2868                         bytes_per_sector = 512;
2869                         sectors_per_unit = bsize/bytes_per_sector;
2870                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2871 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2872                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2873                         SBIG_UINT(pdata,0,dsize);
2874                         SBIG_UINT(pdata,8,dfree);
2875                         SIVAL(pdata,16,sectors_per_unit);
2876                         SIVAL(pdata,20,bytes_per_sector);
2877                         break;
2878                 }
2879
2880                 case SMB_FS_FULL_SIZE_INFORMATION:
2881                 {
2882                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2883                         data_len = 32;
2884                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2885                                 return map_nt_error_from_unix(errno);
2886                         }
2887                         block_size = lp_block_size(snum);
2888                         if (bsize < block_size) {
2889                                 uint64_t factor = block_size/bsize;
2890                                 bsize = block_size;
2891                                 dsize /= factor;
2892                                 dfree /= factor;
2893                         }
2894                         if (bsize > block_size) {
2895                                 uint64_t factor = bsize/block_size;
2896                                 bsize = block_size;
2897                                 dsize *= factor;
2898                                 dfree *= factor;
2899                         }
2900                         bytes_per_sector = 512;
2901                         sectors_per_unit = bsize/bytes_per_sector;
2902                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2903 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2904                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2905                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2906                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2907                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2908                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2909                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2910                         break;
2911                 }
2912
2913                 case SMB_QUERY_FS_DEVICE_INFO:
2914                 case SMB_FS_DEVICE_INFORMATION:
2915                         data_len = 8;
2916                         SIVAL(pdata,0,0); /* dev type */
2917                         SIVAL(pdata,4,0); /* characteristics */
2918                         break;
2919
2920 #ifdef HAVE_SYS_QUOTAS
2921                 case SMB_FS_QUOTA_INFORMATION:
2922                 /* 
2923                  * what we have to send --metze:
2924                  *
2925                  * Unknown1:            24 NULL bytes
2926                  * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2927                  * Hard Quota Limit:    8 bytes seems like uint64_t or so
2928                  * Quota Flags:         2 byte :
2929                  * Unknown3:            6 NULL bytes
2930                  *
2931                  * 48 bytes total
2932                  * 
2933                  * details for Quota Flags:
2934                  * 
2935                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2936                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2937                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2938                  * 0x0001 Enable Quotas: enable quota for this fs
2939                  *
2940                  */
2941                 {
2942                         /* we need to fake up a fsp here,
2943                          * because its not send in this call
2944                          */
2945                         files_struct fsp;
2946                         SMB_NTQUOTA_STRUCT quotas;
2947
2948                         ZERO_STRUCT(fsp);
2949                         ZERO_STRUCT(quotas);
2950
2951                         fsp.conn = conn;
2952                         fsp.fnum = -1;
2953
2954                         /* access check */
2955                         if (conn->server_info->utok.uid != sec_initial_uid()) {
2956                                 DEBUG(0,("set_user_quota: access_denied "
2957                                          "service [%s] user [%s]\n",
2958                                          lp_servicename(SNUM(conn)),
2959                                          conn->server_info->unix_name));
2960                                 return NT_STATUS_ACCESS_DENIED;
2961                         }
2962
2963                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2964                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2965                                 return map_nt_error_from_unix(errno);
2966                         }
2967
2968                         data_len = 48;
2969
2970                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2971                                   lp_servicename(SNUM(conn))));
2972
2973                         /* Unknown1 24 NULL bytes*/
2974                         SBIG_UINT(pdata,0,(uint64_t)0);
2975                         SBIG_UINT(pdata,8,(uint64_t)0);
2976                         SBIG_UINT(pdata,16,(uint64_t)0);
2977
2978                         /* Default Soft Quota 8 bytes */
2979                         SBIG_UINT(pdata,24,quotas.softlim);
2980
2981                         /* Default Hard Quota 8 bytes */
2982                         SBIG_UINT(pdata,32,quotas.hardlim);
2983
2984                         /* Quota flag 2 bytes */
2985                         SSVAL(pdata,40,quotas.qflags);
2986
2987                         /* Unknown3 6 NULL bytes */
2988                         SSVAL(pdata,42,0);
2989                         SIVAL(pdata,44,0);
2990
2991                         break;
2992                 }
2993 #endif /* HAVE_SYS_QUOTAS */
2994                 case SMB_FS_OBJECTID_INFORMATION:
2995                 {
2996                         unsigned char objid[16];
2997                         struct smb_extended_info extended_info;
2998                         memcpy(pdata,create_volume_objectid(conn, objid),16);
2999                         samba_extended_info_version (&extended_info);
3000                         SIVAL(pdata,16,extended_info.samba_magic);
3001                         SIVAL(pdata,20,extended_info.samba_version);
3002                         SIVAL(pdata,24,extended_info.samba_subversion);
3003                         SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3004                         memcpy(pdata+36,extended_info.samba_version_string,28);
3005                         data_len = 64;
3006                         break;
3007                 }
3008
3009                 /*
3010                  * Query the version and capabilities of the CIFS UNIX extensions
3011                  * in use.
3012                  */
3013
3014                 case SMB_QUERY_CIFS_UNIX_INFO:
3015                 {
3016                         bool large_write = lp_min_receive_file_size() &&
3017                                         !srv_is_signing_active(smbd_server_conn);
3018                         bool large_read = !srv_is_signing_active(smbd_server_conn);
3019                         int encrypt_caps = 0;
3020
3021                         if (!lp_unix_extensions()) {
3022                                 return NT_STATUS_INVALID_LEVEL;
3023                         }
3024
3025                         switch (conn->encrypt_level) {
3026                         case 0:
3027                                 encrypt_caps = 0;
3028                                 break;
3029                         case 1:
3030                         case Auto:
3031                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3032                                 break;
3033                         case Required:
3034                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3035                                                 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3036                                 large_write = false;
3037                                 large_read = false;
3038                                 break;
3039                         }
3040
3041                         data_len = 12;
3042                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3043                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3044
3045                         /* We have POSIX ACLs, pathname, encryption, 
3046                          * large read/write, and locking capability. */
3047
3048                         SBIG_UINT(pdata,4,((uint64_t)(
3049                                         CIFS_UNIX_POSIX_ACLS_CAP|
3050                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
3051                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
3052                                         CIFS_UNIX_EXTATTR_CAP|
3053                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3054                                         encrypt_caps|
3055                                         (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3056                                         (large_write ?
3057                                         CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3058                         break;
3059                 }
3060
3061                 case SMB_QUERY_POSIX_FS_INFO:
3062                 {
3063                         int rc;
3064                         vfs_statvfs_struct svfs;
3065
3066                         if (!lp_unix_extensions()) {
3067                                 return NT_STATUS_INVALID_LEVEL;
3068                         }
3069
3070                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3071
3072                         if (!rc) {
3073                                 data_len = 56;
3074                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
3075                                 SIVAL(pdata,4,svfs.BlockSize);
3076                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3077                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3078                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3079                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3080                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3081                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3082                                 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3083 #ifdef EOPNOTSUPP
3084                         } else if (rc == EOPNOTSUPP) {
3085                                 return NT_STATUS_INVALID_LEVEL;
3086 #endif /* EOPNOTSUPP */
3087                         } else {
3088                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3089                                 return NT_STATUS_DOS(ERRSRV, ERRerror);
3090                         }
3091                         break;
3092                 }
3093
3094                 case SMB_QUERY_POSIX_WHOAMI:
3095                 {
3096                         uint32_t flags = 0;
3097                         uint32_t sid_bytes;
3098                         int i;
3099
3100                         if (!lp_unix_extensions()) {
3101                                 return NT_STATUS_INVALID_LEVEL;
3102                         }
3103
3104                         if (max_data_bytes < 40) {
3105                                 return NT_STATUS_BUFFER_TOO_SMALL;
3106                         }
3107
3108                         /* We ARE guest if global_sid_Builtin_Guests is
3109                          * in our list of SIDs.
3110                          */
3111                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
3112                                                conn->server_info->ptok)) {
3113                                 flags |= SMB_WHOAMI_GUEST;
3114                         }
3115
3116                         /* We are NOT guest if global_sid_Authenticated_Users
3117                          * is in our list of SIDs.
3118                          */
3119                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
3120                                                conn->server_info->ptok)) {
3121                                 flags &= ~SMB_WHOAMI_GUEST;
3122                         }
3123
3124                         /* NOTE: 8 bytes for UID/GID, irrespective of native
3125                          * platform size. This matches
3126                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
3127                          */
3128                         data_len = 4 /* flags */
3129                             + 4 /* flag mask */
3130                             + 8 /* uid */
3131                             + 8 /* gid */
3132                             + 4 /* ngroups */
3133                             + 4 /* num_sids */
3134                             + 4 /* SID bytes */
3135                             + 4 /* pad/reserved */
3136                             + (conn->server_info->utok.ngroups * 8)
3137                                 /* groups list */
3138                             + (conn->server_info->ptok->num_sids *
3139                                     SID_MAX_SIZE)
3140                                 /* SID list */;
3141
3142                         SIVAL(pdata, 0, flags);
3143                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3144                         SBIG_UINT(pdata, 8,
3145                                   (uint64_t)conn->server_info->utok.uid);
3146                         SBIG_UINT(pdata, 16,
3147                                   (uint64_t)conn->server_info->utok.gid);
3148
3149
3150                         if (data_len >= max_data_bytes) {
3151                                 /* Potential overflow, skip the GIDs and SIDs. */
3152
3153                                 SIVAL(pdata, 24, 0); /* num_groups */
3154                                 SIVAL(pdata, 28, 0); /* num_sids */
3155                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3156                                 SIVAL(pdata, 36, 0); /* reserved */
3157
3158                                 data_len = 40;
3159                                 break;
3160                         }
3161
3162                         SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3163                         SIVAL(pdata, 28, conn->server_info->num_sids);
3164
3165                         /* We walk the SID list twice, but this call is fairly
3166                          * infrequent, and I don't expect that it's performance
3167                          * sensitive -- jpeach
3168                          */
3169                         for (i = 0, sid_bytes = 0;
3170                              i < conn->server_info->ptok->num_sids; ++i) {
3171                                 sid_bytes += ndr_size_dom_sid(
3172                                         &conn->server_info->ptok->user_sids[i],
3173                                         NULL, 
3174                                         0);
3175                         }
3176
3177                         /* SID list byte count */
3178                         SIVAL(pdata, 32, sid_bytes);
3179
3180                         /* 4 bytes pad/reserved - must be zero */
3181                         SIVAL(pdata, 36, 0);
3182                         data_len = 40;
3183
3184                         /* GID list */
3185                         for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3186                                 SBIG_UINT(pdata, data_len,
3187                                           (uint64_t)conn->server_info->utok.groups[i]);
3188                                 data_len += 8;
3189                         }
3190
3191                         /* SID list */
3192                         for (i = 0;
3193                             i < conn->server_info->ptok->num_sids; ++i) {
3194                                 int sid_len = ndr_size_dom_sid(
3195                                         &conn->server_info->ptok->user_sids[i],
3196                                         NULL,
3197                                         0);
3198
3199                                 sid_linearize(pdata + data_len, sid_len,
3200                                     &conn->server_info->ptok->user_sids[i]);
3201                                 data_len += sid_len;
3202                         }
3203
3204                         break;
3205                 }
3206
3207                 case SMB_MAC_QUERY_FS_INFO:
3208                         /*
3209                          * Thursby MAC extension... ONLY on NTFS filesystems
3210                          * once we do streams then we don't need this
3211                          */
3212                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3213                                 data_len = 88;
3214                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
3215                                 break;
3216                         }
3217                         /* drop through */
3218                 default:
3219                         return NT_STATUS_INVALID_LEVEL;
3220         }
3221
3222         *ret_data_len = data_len;
3223         return NT_STATUS_OK;
3224 }
3225
3226 /****************************************************************************
3227  Reply to a TRANS2_QFSINFO (query filesystem info).
3228 ****************************************************************************/
3229
3230 static void call_trans2qfsinfo(connection_struct *conn,
3231                                struct smb_request *req,
3232                                char **pparams, int total_params,
3233                                char **ppdata, int total_data,
3234                                unsigned int max_data_bytes)
3235 {
3236         char *params = *pparams;
3237         uint16_t info_level;
3238         int data_len = 0;
3239         SMB_STRUCT_STAT st;
3240         NTSTATUS status;
3241
3242         if (total_params < 2) {
3243                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3244                 return;
3245         }
3246
3247         info_level = SVAL(params,0);
3248
3249         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3250                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3251                         DEBUG(0,("call_trans2qfsinfo: encryption required "
3252                                 "and info level 0x%x sent.\n",
3253                                 (unsigned int)info_level));
3254                         exit_server_cleanly("encryption required "
3255                                 "on connection");
3256                         return;
3257                 }
3258         }
3259
3260         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3261
3262         if(vfs_stat_smb_fname(conn,".",&st)!=0) {
3263                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
3264                 reply_doserror(req, ERRSRV, ERRinvdevice);
3265                 return;
3266         }
3267
3268         status = smbd_do_qfsinfo(conn, req,
3269                                  info_level, st,
3270                                  req->flags2,
3271                                  max_data_bytes,
3272                                  ppdata, &data_len);
3273         if (!NT_STATUS_IS_OK(status)) {
3274                 reply_nterror(req, status);
3275                 return;
3276         }
3277
3278         send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3279                             max_data_bytes);
3280
3281         DEBUG( 4, ( "%s info_level = %d\n",
3282                     smb_fn_name(req->cmd), info_level) );
3283
3284         return;
3285 }
3286
3287 /****************************************************************************
3288  Reply to a TRANS2_SETFSINFO (set filesystem info).
3289 ****************************************************************************/
3290
3291 static void call_trans2setfsinfo(connection_struct *conn,
3292                                  struct smb_request *req,
3293                                  char **pparams, int total_params,
3294                                  char **ppdata, int total_data,
3295                                  unsigned int max_data_bytes)
3296 {
3297         char *pdata = *ppdata;
3298         char *params = *pparams;
3299         uint16 info_level;
3300
3301         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3302
3303         /*  */
3304         if (total_params < 4) {
3305                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3306                         total_params));
3307                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3308                 return;
3309         }
3310
3311         info_level = SVAL(params,2);
3312
3313         if (IS_IPC(conn)) {
3314                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3315                                 info_level != SMB_SET_CIFS_UNIX_INFO) {
3316                         DEBUG(0,("call_trans2setfsinfo: not an allowed "
3317                                 "info level (0x%x) on IPC$.\n",
3318                                 (unsigned int)info_level));
3319                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3320                         return;
3321                 }
3322         }
3323
3324         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3325                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3326                         DEBUG(0,("call_trans2setfsinfo: encryption required "
3327                                 "and info level 0x%x sent.\n",
3328                                 (unsigned int)info_level));
3329                         exit_server_cleanly("encryption required "
3330                                 "on connection");
3331                         return;
3332                 }
3333         }
3334
3335         switch(info_level) {
3336                 case SMB_SET_CIFS_UNIX_INFO:
3337                         {
3338                                 uint16 client_unix_major;
3339                                 uint16 client_unix_minor;
3340                                 uint32 client_unix_cap_low;
3341                                 uint32 client_unix_cap_high;
3342
3343                                 if (!lp_unix_extensions()) {
3344                                         reply_nterror(req,
3345                                                       NT_STATUS_INVALID_LEVEL);
3346                                         return;
3347                                 }
3348
3349                                 /* There should be 12 bytes of capabilities set. */
3350                                 if (total_data < 8) {
3351                                         reply_nterror(
3352                                                 req,
3353                                                 NT_STATUS_INVALID_PARAMETER);
3354                                         return;
3355                                 }
3356                                 client_unix_major = SVAL(pdata,0);
3357                                 client_unix_minor = SVAL(pdata,2);
3358                                 client_unix_cap_low = IVAL(pdata,4);
3359                                 client_unix_cap_high = IVAL(pdata,8);
3360                                 /* Just print these values for now. */
3361                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3362 cap_low = 0x%x, cap_high = 0x%x\n",
3363                                         (unsigned int)client_unix_major,
3364                                         (unsigned int)client_unix_minor,
3365                                         (unsigned int)client_unix_cap_low,
3366                                         (unsigned int)client_unix_cap_high ));
3367
3368                                 /* Here is where we must switch to posix pathname processing... */
3369                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3370                                         lp_set_posix_pathnames();
3371                                         mangle_change_to_posix();
3372                                 }
3373
3374                                 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3375                                     !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3376                                         /* Client that knows how to do posix locks,
3377                                          * but not posix open/mkdir operations. Set a
3378                                          * default type for read/write checks. */
3379
3380                                         lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3381
3382                                 }
3383                                 break;
3384                         }
3385
3386                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3387                         {
3388                                 NTSTATUS status;
3389                                 size_t param_len = 0;
3390                                 size_t data_len = total_data;
3391
3392                                 if (!lp_unix_extensions()) {
3393                                         reply_nterror(
3394                                                 req,
3395                                                 NT_STATUS_INVALID_LEVEL);
3396                                         return;
3397                                 }
3398
3399                                 if (lp_smb_encrypt(SNUM(conn)) == false) {
3400                                         reply_nterror(
3401                                                 req,
3402                                                 NT_STATUS_NOT_SUPPORTED);
3403                                         return;
3404                                 }
3405
3406                                 DEBUG( 4,("call_trans2setfsinfo: "
3407                                         "request transport encryption.\n"));
3408
3409                                 status = srv_request_encryption_setup(conn,
3410                                                                 (unsigned char **)ppdata,
3411                                                                 &data_len,
3412                                                                 (unsigned char **)pparams,
3413                                                                 &param_len);
3414
3415                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3416                                                 !NT_STATUS_IS_OK(status)) {
3417                                         reply_nterror(req, status);
3418                                         return;
3419                                 }
3420
3421                                 send_trans2_replies(conn, req,
3422                                                 *pparams,
3423                                                 param_len,
3424                                                 *ppdata,
3425                                                 data_len,
3426                                                 max_data_bytes);
3427
3428                                 if (NT_STATUS_IS_OK(status)) {
3429                                         /* Server-side transport
3430                                          * encryption is now *on*. */
3431                                         status = srv_encryption_start(conn);
3432                                         if (!NT_STATUS_IS_OK(status)) {
3433                                                 exit_server_cleanly(
3434                                                         "Failure in setting "
3435                                                         "up encrypted transport");
3436                                         }
3437                                 }
3438                                 return;
3439                         }
3440
3441                 case SMB_FS_QUOTA_INFORMATION:
3442                         {
3443                                 files_struct *fsp = NULL;
3444                                 SMB_NTQUOTA_STRUCT quotas;
3445
3446                                 ZERO_STRUCT(quotas);
3447
3448                                 /* access check */
3449                                 if ((conn->server_info->utok.uid != sec_initial_uid())
3450                                     ||!CAN_WRITE(conn)) {
3451                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3452                                                  lp_servicename(SNUM(conn)),
3453                                                  conn->server_info->unix_name));
3454                                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3455                                         return;
3456                                 }
3457
3458                                 /* note: normaly there're 48 bytes,
3459                                  * but we didn't use the last 6 bytes for now 
3460                                  * --metze 
3461                                  */
3462                                 fsp = file_fsp(req, SVAL(params,0));
3463
3464                                 if (!check_fsp_ntquota_handle(conn, req,
3465                                                               fsp)) {
3466                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3467                                         reply_nterror(
3468                                                 req, NT_STATUS_INVALID_HANDLE);
3469                                         return;
3470                                 }
3471
3472                                 if (total_data < 42) {
3473                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3474                                                 total_data));
3475                                         reply_nterror(
3476                                                 req,
3477                                                 NT_STATUS_INVALID_PARAMETER);
3478                                         return;
3479                                 }
3480
3481                                 /* unknown_1 24 NULL bytes in pdata*/
3482
3483                                 /* the soft quotas 8 bytes (uint64_t)*/
3484                                 quotas.softlim = (uint64_t)IVAL(pdata,24);
3485 #ifdef LARGE_SMB_OFF_T
3486                                 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3487 #else /* LARGE_SMB_OFF_T */
3488                                 if ((IVAL(pdata,28) != 0)&&
3489                                         ((quotas.softlim != 0xFFFFFFFF)||
3490                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
3491                                         /* more than 32 bits? */
3492                                         reply_nterror(
3493                                                 req,
3494                                                 NT_STATUS_INVALID_PARAMETER);
3495                                         return;
3496                                 }
3497 #endif /* LARGE_SMB_OFF_T */
3498
3499                                 /* the hard quotas 8 bytes (uint64_t)*/
3500                                 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3501 #ifdef LARGE_SMB_OFF_T
3502                                 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3503 #else /* LARGE_SMB_OFF_T */
3504                                 if ((IVAL(pdata,36) != 0)&&
3505                                         ((quotas.hardlim != 0xFFFFFFFF)||
3506                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
3507                                         /* more than 32 bits? */
3508                                         reply_nterror(
3509                                                 req,
3510                                                 NT_STATUS_INVALID_PARAMETER);
3511                                         return;
3512                                 }
3513 #endif /* LARGE_SMB_OFF_T */
3514
3515                                 /* quota_flags 2 bytes **/
3516                                 quotas.qflags = SVAL(pdata,40);
3517
3518                                 /* unknown_2 6 NULL bytes follow*/
3519
3520                                 /* now set the quotas */
3521                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3522                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3523                                         reply_nterror(req, map_nt_error_from_unix(errno));
3524                                         return;
3525                                 }
3526
3527                                 break;
3528                         }
3529                 default:
3530                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3531                                 info_level));
3532                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3533                         return;
3534                         break;
3535         }
3536
3537         /* 
3538          * sending this reply works fine, 
3539          * but I'm not sure it's the same 
3540          * like windows do...
3541          * --metze
3542          */
3543         reply_outbuf(req, 10, 0);
3544 }
3545
3546 #if defined(HAVE_POSIX_ACLS)
3547 /****************************************************************************
3548  Utility function to count the number of entries in a POSIX acl.
3549 ****************************************************************************/
3550
3551 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3552 {
3553         unsigned int ace_count = 0;
3554         int entry_id = SMB_ACL_FIRST_ENTRY;
3555         SMB_ACL_ENTRY_T entry;
3556
3557         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3558                 /* get_next... */
3559                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3560                         entry_id = SMB_ACL_NEXT_ENTRY;
3561                 }
3562                 ace_count++;
3563         }
3564         return ace_count;
3565 }
3566
3567 /****************************************************************************
3568  Utility function to marshall a POSIX acl into wire format.
3569 ****************************************************************************/
3570
3571 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3572 {
3573         int entry_id = SMB_ACL_FIRST_ENTRY;
3574         SMB_ACL_ENTRY_T entry;
3575
3576         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3577                 SMB_ACL_TAG_T tagtype;
3578                 SMB_ACL_PERMSET_T permset;
3579                 unsigned char perms = 0;
3580                 unsigned int own_grp;
3581
3582                 /* get_next... */
3583                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3584                         entry_id = SMB_ACL_NEXT_ENTRY;
3585                 }
3586
3587                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3588                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3589                         return False;
3590                 }
3591
3592                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3593                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3594                         return False;
3595                 }
3596
3597                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3598                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3599                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3600
3601                 SCVAL(pdata,1,perms);
3602
3603                 switch (tagtype) {
3604                         case SMB_ACL_USER_OBJ:
3605                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3606                                 own_grp = (unsigned int)pst->st_ex_uid;
3607                                 SIVAL(pdata,2,own_grp);
3608                                 SIVAL(pdata,6,0);
3609                                 break;
3610                         case SMB_ACL_USER:
3611                                 {
3612                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3613                                         if (!puid) {
3614                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3615                                                 return False;
3616                                         }
3617                                         own_grp = (unsigned int)*puid;
3618                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3619                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3620                                         SIVAL(pdata,2,own_grp);
3621                                         SIVAL(pdata,6,0);
3622                                         break;
3623                                 }
3624                         case SMB_ACL_GROUP_OBJ:
3625                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3626                                 own_grp = (unsigned int)pst->st_ex_gid;
3627                                 SIVAL(pdata,2,own_grp);
3628                                 SIVAL(pdata,6,0);
3629                                 break;
3630                         case SMB_ACL_GROUP:
3631                                 {
3632                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3633                                         if (!pgid) {
3634                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3635                                                 return False;
3636                                         }
3637                                         own_grp = (unsigned int)*pgid;
3638                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3639                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3640                                         SIVAL(pdata,2,own_grp);
3641                                         SIVAL(pdata,6,0);
3642                                         break;
3643                                 }
3644                         case SMB_ACL_MASK:
3645                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3646                                 SIVAL(pdata,2,0xFFFFFFFF);
3647                                 SIVAL(pdata,6,0xFFFFFFFF);
3648                                 break;
3649                         case SMB_ACL_OTHER:
3650                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3651                                 SIVAL(pdata,2,0xFFFFFFFF);
3652                                 SIVAL(pdata,6,0xFFFFFFFF);
3653                                 break;
3654                         default:
3655                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3656                                 return False;
3657                 }
3658                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3659         }
3660
3661         return True;
3662 }
3663 #endif
3664
3665 /****************************************************************************
3666  Store the FILE_UNIX_BASIC info.
3667 ****************************************************************************/
3668
3669 static char *store_file_unix_basic(connection_struct *conn,
3670                                 char *pdata,
3671                                 files_struct *fsp,
3672                                 const SMB_STRUCT_STAT *psbuf)
3673 {
3674         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3675         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3676
3677         SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
3678         pdata += 8;
3679
3680         SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3681         pdata += 8;
3682
3683         put_long_date_timespec(pdata, psbuf->st_ex_ctime);       /* Change Time 64 Bit */
3684         put_long_date_timespec(pdata+8, psbuf->st_ex_atime);     /* Last access time 64 Bit */
3685         put_long_date_timespec(pdata+16, psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
3686         pdata += 24;
3687
3688         SIVAL(pdata,0,psbuf->st_ex_uid);               /* user id for the owner */
3689         SIVAL(pdata,4,0);
3690         pdata += 8;
3691
3692         SIVAL(pdata,0,psbuf->st_ex_gid);               /* group id of owner */
3693         SIVAL(pdata,4,0);
3694         pdata += 8;
3695
3696         SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3697         pdata += 4;
3698
3699         SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev));   /* Major device number if type is device */
3700         SIVAL(pdata,4,0);
3701         pdata += 8;
3702
3703         SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev));   /* Minor device number if type is device */
3704         SIVAL(pdata,4,0);
3705         pdata += 8;
3706
3707         SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino);   /* inode number */
3708         pdata += 8;
3709
3710         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode));     /* Standard UNIX file permissions */
3711         SIVAL(pdata,4,0);
3712         pdata += 8;
3713
3714         SIVAL(pdata,0,psbuf->st_ex_nlink);             /* number of hard links */
3715         SIVAL(pdata,4,0);
3716         pdata += 8;
3717
3718         return pdata;
3719 }
3720
3721 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3722  * the chflags(2) (or equivalent) flags.
3723  *
3724  * XXX: this really should be behind the VFS interface. To do this, we would
3725  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3726  * Each VFS module could then implement its own mapping as appropriate for the
3727  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3728  */
3729 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3730         info2_flags_map[] =
3731 {
3732 #ifdef UF_NODUMP
3733     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3734 #endif
3735
3736 #ifdef UF_IMMUTABLE
3737     { UF_IMMUTABLE, EXT_IMMUTABLE },
3738 #endif
3739
3740 #ifdef UF_APPEND
3741     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3742 #endif
3743
3744 #ifdef UF_HIDDEN
3745     { UF_HIDDEN, EXT_HIDDEN },
3746 #endif
3747
3748     /* Do not remove. We need to guarantee that this array has at least one
3749      * entry to build on HP-UX.
3750      */
3751     { 0, 0 }
3752
3753 };
3754
3755 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3756                                 uint32 *smb_fflags, uint32 *smb_fmask)
3757 {
3758         int i;
3759
3760         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3761             *smb_fmask |= info2_flags_map[i].smb_fflag;
3762             if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3763                     *smb_fflags |= info2_flags_map[i].smb_fflag;
3764             }
3765         }
3766 }
3767
3768 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3769                                 const uint32 smb_fflags,
3770                                 const uint32 smb_fmask,
3771                                 int *stat_fflags)
3772 {
3773         uint32 max_fmask = 0;
3774         int i;
3775
3776         *stat_fflags = psbuf->st_ex_flags;
3777
3778         /* For each flags requested in smb_fmask, check the state of the
3779          * corresponding flag in smb_fflags and set or clear the matching
3780          * stat flag.
3781          */
3782
3783         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3784             max_fmask |= info2_flags_map[i].smb_fflag;
3785             if (smb_fmask & info2_flags_map[i].smb_fflag) {
3786                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
3787                             *stat_fflags |= info2_flags_map[i].stat_fflag;
3788                     } else {
3789                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3790                     }
3791             }
3792         }
3793
3794         /* If smb_fmask is asking to set any bits that are not supported by
3795          * our flag mappings, we should fail.
3796          */
3797         if ((smb_fmask & max_fmask) != smb_fmask) {
3798                 return False;
3799         }
3800
3801         return True;
3802 }
3803
3804
3805 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3806  * of file flags and birth (create) time.
3807  */
3808 static char *store_file_unix_basic_info2(connection_struct *conn,
3809                                 char *pdata,
3810                                 files_struct *fsp,
3811                                 const SMB_STRUCT_STAT *psbuf)
3812 {
3813         uint32 file_flags = 0;
3814         uint32 flags_mask = 0;
3815
3816         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3817
3818         /* Create (birth) time 64 bit */
3819         put_long_date_timespec(pdata, psbuf->st_ex_btime);
3820         pdata += 8;
3821
3822         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3823         SIVAL(pdata, 0, file_flags); /* flags */
3824         SIVAL(pdata, 4, flags_mask); /* mask */
3825         pdata += 8;
3826
3827         return pdata;
3828 }
3829
3830 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3831                                      const struct stream_struct *streams,
3832                                      char *data,
3833                                      unsigned int max_data_bytes,
3834                                      unsigned int *data_size)
3835 {
3836         unsigned int i;
3837         unsigned int ofs = 0;
3838
3839         for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3840                 unsigned int next_offset;
3841                 size_t namelen;
3842                 smb_ucs2_t *namebuf;
3843
3844                 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3845                                       streams[i].name, &namelen) ||
3846                     namelen <= 2)
3847                 {
3848                         return NT_STATUS_INVALID_PARAMETER;
3849                 }
3850
3851                 /*
3852                  * name_buf is now null-terminated, we need to marshall as not
3853                  * terminated
3854                  */
3855
3856                 namelen -= 2;
3857
3858                 SIVAL(data, ofs+4, namelen);
3859                 SOFF_T(data, ofs+8, streams[i].size);
3860                 SOFF_T(data, ofs+16, streams[i].alloc_size);
3861                 memcpy(data+ofs+24, namebuf, namelen);
3862                 TALLOC_FREE(namebuf);
3863
3864                 next_offset = ofs + 24 + namelen;
3865
3866                 if (i == num_streams-1) {
3867                         SIVAL(data, ofs, 0);
3868                 }
3869                 else {
3870                         unsigned int align = ndr_align_size(next_offset, 8);
3871
3872                         memset(data+next_offset, 0, align);
3873                         next_offset += align;
3874
3875                         SIVAL(data, ofs, next_offset - ofs);
3876                         ofs = next_offset;
3877                 }
3878
3879                 ofs = next_offset;
3880         }
3881
3882         *data_size = ofs;
3883
3884         return NT_STATUS_OK;
3885 }
3886
3887 /****************************************************************************
3888  Reply to a TRANSACT2_QFILEINFO on a PIPE !
3889 ****************************************************************************/
3890
3891 static void call_trans2qpipeinfo(connection_struct *conn,
3892                                  struct smb_request *req,
3893                                  unsigned int tran_call,
3894                                  char **pparams, int total_params,
3895                                  char **ppdata, int total_data,
3896                                  unsigned int max_data_bytes)
3897 {
3898         char *params = *pparams;
3899         char *pdata = *ppdata;
3900         unsigned int data_size = 0;
3901         unsigned int param_size = 2;
3902         uint16 info_level;
3903         files_struct *fsp;
3904
3905         if (!params) {
3906                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3907                 return;
3908         }
3909
3910         if (total_params < 4) {
3911                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3912                 return;
3913         }
3914
3915         fsp = file_fsp(req, SVAL(params,0));
3916         if (!fsp_is_np(fsp)) {
3917                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3918                 return;
3919         }
3920
3921         info_level = SVAL(params,2);
3922
3923         *pparams = (char *)SMB_REALLOC(*pparams,2);
3924         if (*pparams == NULL) {
3925                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3926                 return;
3927         }
3928         params = *pparams;
3929         SSVAL(params,0,0);
3930         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3931         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3932         if (*ppdata == NULL ) {
3933                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3934                 return;
3935         }
3936         pdata = *ppdata;
3937
3938         switch (info_level) {
3939                 case SMB_FILE_STANDARD_INFORMATION:
3940                         memset(pdata,0,24);
3941                         SOFF_T(pdata,0,4096LL);
3942                         SIVAL(pdata,16,1);
3943                         SIVAL(pdata,20,1);
3944                         data_size = 24;
3945                         break;
3946
3947                 default:
3948                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3949                         return;
3950         }
3951
3952         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3953                             max_data_bytes);
3954
3955         return;
3956 }
3957
3958 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3959                                TALLOC_CTX *mem_ctx,
3960                                uint16_t info_level,
3961                                files_struct *fsp,
3962                                const struct smb_filename *smb_fname,
3963                                bool delete_pending,
3964                                struct timespec write_time_ts,
3965                                bool ms_dfs_link,
3966                                struct ea_list *ea_list,
3967                                int lock_data_count,
3968                                char *lock_data,
3969                                uint16_t flags2,
3970                                unsigned int max_data_bytes,
3971                                char **ppdata,
3972                                unsigned int *pdata_size)
3973 {
3974         char *pdata = *ppdata;
3975         char *dstart, *dend;
3976         unsigned int data_size;
3977         struct timespec create_time_ts, mtime_ts, atime_ts;
3978         time_t create_time, mtime, atime;
3979         SMB_STRUCT_STAT sbuf;
3980         char *p;
3981         char *fname;
3982         char *base_name;
3983         char *dos_fname;
3984         int mode;
3985         int nlink;
3986         NTSTATUS status;
3987         uint64_t file_size = 0;
3988         uint64_t pos = 0;
3989         uint64_t allocation_size = 0;
3990         uint64_t file_index = 0;
3991         uint32_t access_mask = 0;
3992
3993         sbuf = smb_fname->st;
3994
3995         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3996                 return NT_STATUS_INVALID_LEVEL;
3997         }
3998
3999         status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
4000         if (!NT_STATUS_IS_OK(status)) {
4001                 return status;
4002         }
4003
4004         DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4005                 fname, fsp ? fsp->fnum : -1, info_level, max_data_bytes));
4006
4007         if (ms_dfs_link) {
4008                 mode = dos_mode_msdfs(conn, smb_fname);
4009         } else {
4010                 mode = dos_mode(conn, smb_fname);
4011         }
4012         if (!mode)
4013                 mode = FILE_ATTRIBUTE_NORMAL;
4014
4015         nlink = sbuf.st_ex_nlink;
4016
4017         if (nlink && (mode&aDIR)) {
4018                 nlink = 1;
4019         }
4020
4021         if ((nlink > 0) && delete_pending) {
4022                 nlink -= 1;
4023         }
4024
4025         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4026         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4027         if (*ppdata == NULL) {
4028                 return NT_STATUS_NO_MEMORY;
4029         }
4030         pdata = *ppdata;
4031         dstart = pdata;
4032         dend = dstart + data_size - 1;
4033
4034         if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4035                 update_stat_ex_mtime(&sbuf, write_time_ts);
4036         }
4037
4038         create_time_ts = sbuf.st_ex_btime;
4039         mtime_ts = sbuf.st_ex_mtime;
4040         atime_ts = sbuf.st_ex_atime;
4041
4042         if (lp_dos_filetime_resolution(SNUM(conn))) {
4043                 dos_filetime_timespec(&create_time_ts);
4044                 dos_filetime_timespec(&mtime_ts);
4045                 dos_filetime_timespec(&atime_ts);
4046         }
4047
4048         create_time = convert_timespec_to_time_t(create_time_ts);
4049         mtime = convert_timespec_to_time_t(mtime_ts);
4050         atime = convert_timespec_to_time_t(atime_ts);
4051
4052         p = strrchr_m(smb_fname->base_name,'/');
4053         if (!p)
4054                 base_name = smb_fname->base_name;
4055         else
4056                 base_name = p+1;
4057
4058         /* NT expects the name to be in an exact form of the *full*
4059            filename. See the trans2 torture test */
4060         if (ISDOT(base_name)) {
4061                 dos_fname = talloc_strdup(mem_ctx, "\\");
4062                 if (!dos_fname) {
4063                         return NT_STATUS_NO_MEMORY;
4064                 }
4065         } else {
4066                 dos_fname = talloc_asprintf(mem_ctx,
4067                                 "\\%s",
4068                                 fname);
4069                 if (!dos_fname) {
4070                         return NT_STATUS_NO_MEMORY;
4071                 }
4072                 string_replace(dos_fname, '/', '\\');
4073         }
4074
4075         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4076
4077         if (!fsp) {
4078                 /* Do we have this path open ? */
4079                 files_struct *fsp1;
4080                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4081                 fsp1 = file_find_di_first(fileid);
4082                 if (fsp1 && fsp1->initial_allocation_size) {
4083                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4084                 }
4085         }
4086
4087         if (!(mode & aDIR)) {
4088                 file_size = get_file_size_stat(&sbuf);
4089         }
4090
4091         if (fsp) {
4092                 pos = fsp->fh->position_information;
4093         }
4094
4095         if (fsp) {
4096                 access_mask = fsp->access_mask;
4097         } else {
4098                 /* GENERIC_EXECUTE mapping from Windows */
4099                 access_mask = 0x12019F;
4100         }
4101
4102         /* This should be an index number - looks like
4103            dev/ino to me :-)
4104
4105            I think this causes us to fail the IFSKIT
4106            BasicFileInformationTest. -tpot */
4107         file_index =  ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4108         file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4109
4110         switch (info_level) {
4111                 case SMB_INFO_STANDARD:
4112                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4113                         data_size = 22;
4114                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4115                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4116                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4117                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
4118                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4119                         SSVAL(pdata,l1_attrFile,mode);
4120                         break;
4121
4122                 case SMB_INFO_QUERY_EA_SIZE:
4123                 {
4124                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4125                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4126                         data_size = 26;
4127                         srv_put_dos_date2(pdata,0,create_time);
4128                         srv_put_dos_date2(pdata,4,atime);
4129                         srv_put_dos_date2(pdata,8,mtime); /* write time */
4130                         SIVAL(pdata,12,(uint32)file_size);
4131                         SIVAL(pdata,16,(uint32)allocation_size);
4132                         SSVAL(pdata,20,mode);
4133                         SIVAL(pdata,22,ea_size);
4134                         break;
4135                 }
4136
4137                 case SMB_INFO_IS_NAME_VALID:
4138                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4139                         if (fsp) {
4140                                 /* os/2 needs this ? really ?*/
4141                                 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4142                         }
4143                         /* This is only reached for qpathinfo */
4144                         data_size = 0;
4145                         break;
4146
4147                 case SMB_INFO_QUERY_EAS_FROM_LIST:
4148                 {
4149                         size_t total_ea_len = 0;
4150                         struct ea_list *ea_file_list = NULL;
4151
4152                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4153
4154                         ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4155                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4156
4157                         if (!ea_list || (total_ea_len > data_size)) {
4158                                 data_size = 4;
4159                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4160                                 break;
4161                         }
4162
4163                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4164                         break;
4165                 }
4166
4167                 case SMB_INFO_QUERY_ALL_EAS:
4168                 {
4169                         /* We have data_size bytes to put EA's into. */
4170                         size_t total_ea_len = 0;
4171
4172                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4173
4174                         ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4175                         if (!ea_list || (total_ea_len > data_size)) {
4176                                 data_size = 4;
4177                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4178                                 break;
4179                         }
4180
4181                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4182                         break;
4183                 }
4184
4185                 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4186                 {
4187                         /* We have data_size bytes to put EA's into. */
4188                         size_t total_ea_len = 0;
4189                         struct ea_list *ea_file_list = NULL;
4190
4191                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4192
4193                         /*TODO: add filtering and index handling */
4194
4195                         ea_file_list = get_ea_list_from_file(mem_ctx,
4196                                                              conn, fsp,
4197                                                              fname,
4198                                                              &total_ea_len);
4199                         if (!ea_file_list) {
4200                                 return NT_STATUS_NO_EAS_ON_FILE;
4201                         }
4202
4203                         status = fill_ea_chained_buffer(mem_ctx,
4204                                                         pdata,
4205                                                         data_size,
4206                                                         &data_size,
4207                                                         conn, ea_file_list);
4208                         if (!NT_STATUS_IS_OK(status)) {
4209                                 return status;
4210                         }
4211                         break;
4212                 }
4213
4214                 case SMB_FILE_BASIC_INFORMATION:
4215                 case SMB_QUERY_FILE_BASIC_INFO:
4216
4217                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4218                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4219                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4220                         } else {
4221                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4222                                 data_size = 40;
4223                                 SIVAL(pdata,36,0);
4224                         }
4225                         put_long_date_timespec(pdata,create_time_ts);
4226                         put_long_date_timespec(pdata+8,atime_ts);
4227                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4228                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4229                         SIVAL(pdata,32,mode);
4230
4231                         DEBUG(5,("SMB_QFBI - "));
4232                         DEBUG(5,("create: %s ", ctime(&create_time)));
4233                         DEBUG(5,("access: %s ", ctime(&atime)));
4234                         DEBUG(5,("write: %s ", ctime(&mtime)));
4235                         DEBUG(5,("change: %s ", ctime(&mtime)));
4236                         DEBUG(5,("mode: %x\n", mode));
4237                         break;
4238
4239                 case SMB_FILE_STANDARD_INFORMATION:
4240                 case SMB_QUERY_FILE_STANDARD_INFO:
4241
4242                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4243                         data_size = 24;
4244                         SOFF_T(pdata,0,allocation_size);
4245                         SOFF_T(pdata,8,file_size);
4246                         SIVAL(pdata,16,nlink);
4247                         SCVAL(pdata,20,delete_pending?1:0);
4248                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4249                         SSVAL(pdata,22,0); /* Padding. */
4250                         break;
4251
4252                 case SMB_FILE_EA_INFORMATION:
4253                 case SMB_QUERY_FILE_EA_INFO:
4254                 {
4255                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4256                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4257                         data_size = 4;
4258                         SIVAL(pdata,0,ea_size);
4259                         break;
4260                 }
4261
4262                 /* Get the 8.3 name - used if NT SMB was negotiated. */
4263                 case SMB_QUERY_FILE_ALT_NAME_INFO:
4264                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4265                 {
4266                         int len;
4267                         char mangled_name[13];
4268                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4269                         if (!name_to_8_3(base_name,mangled_name,
4270                                                 True,conn->params)) {
4271                                 return NT_STATUS_NO_MEMORY;
4272                         }
4273                         len = srvstr_push(dstart, flags2,
4274                                           pdata+4, mangled_name,
4275                                           PTR_DIFF(dend, pdata+4),
4276                                           STR_UNICODE);
4277                         data_size = 4 + len;
4278                         SIVAL(pdata,0,len);
4279                         break;
4280                 }
4281
4282                 case SMB_QUERY_FILE_NAME_INFO:
4283                 {
4284                         int len;
4285                         /*
4286                           this must be *exactly* right for ACLs on mapped drives to work
4287                          */
4288                         len = srvstr_push(dstart, flags2,
4289                                           pdata+4, dos_fname,
4290                                           PTR_DIFF(dend, pdata+4),
4291                                           STR_UNICODE);
4292                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4293                         data_size = 4 + len;
4294                         SIVAL(pdata,0,len);
4295                         break;
4296                 }
4297
4298                 case SMB_FILE_ALLOCATION_INFORMATION:
4299                 case SMB_QUERY_FILE_ALLOCATION_INFO:
4300                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4301                         data_size = 8;
4302                         SOFF_T(pdata,0,allocation_size);
4303                         break;
4304
4305                 case SMB_FILE_END_OF_FILE_INFORMATION:
4306                 case SMB_QUERY_FILE_END_OF_FILEINFO:
4307                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4308                         data_size = 8;
4309                         SOFF_T(pdata,0,file_size);
4310                         break;
4311
4312                 case SMB_QUERY_FILE_ALL_INFO:
4313                 case SMB_FILE_ALL_INFORMATION:
4314                 {
4315                         int len;
4316                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4317                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4318                         put_long_date_timespec(pdata,create_time_ts);
4319                         put_long_date_timespec(pdata+8,atime_ts);
4320                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4321                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4322                         SIVAL(pdata,32,mode);
4323                         SIVAL(pdata,36,0); /* padding. */
4324                         pdata += 40;
4325                         SOFF_T(pdata,0,allocation_size);
4326                         SOFF_T(pdata,8,file_size);
4327                         SIVAL(pdata,16,nlink);
4328                         SCVAL(pdata,20,delete_pending);
4329                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4330                         SSVAL(pdata,22,0);
4331                         pdata += 24;
4332                         SIVAL(pdata,0,ea_size);
4333                         pdata += 4; /* EA info */
4334                         len = srvstr_push(dstart, flags2,
4335                                           pdata+4, dos_fname,
4336                                           PTR_DIFF(dend, pdata+4),
4337                                           STR_UNICODE);
4338                         SIVAL(pdata,0,len);
4339                         pdata += 4 + len;
4340                         data_size = PTR_DIFF(pdata,(*ppdata));
4341                         break;
4342                 }
4343
4344                 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4345                 {
4346                         int len;
4347                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4348                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4349                         put_long_date_timespec(pdata+0x00,create_time_ts);
4350                         put_long_date_timespec(pdata+0x08,atime_ts);
4351                         put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4352                         put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4353                         SIVAL(pdata,    0x20, mode);
4354                         SIVAL(pdata,    0x24, 0); /* padding. */
4355                         SBVAL(pdata,    0x28, allocation_size);
4356                         SBVAL(pdata,    0x30, file_size);
4357                         SIVAL(pdata,    0x38, nlink);
4358                         SCVAL(pdata,    0x3C, delete_pending);
4359                         SCVAL(pdata,    0x3D, (mode&aDIR)?1:0);
4360                         SSVAL(pdata,    0x3E, 0); /* padding */
4361                         SBVAL(pdata,    0x40, file_index);
4362                         SIVAL(pdata,    0x48, ea_size);
4363                         SIVAL(pdata,    0x4C, access_mask);
4364                         SBVAL(pdata,    0x50, pos);
4365                         SIVAL(pdata,    0x58, mode); /*TODO: mode != mode fix this!!! */
4366                         SIVAL(pdata,    0x5C, 0); /* No alignment needed. */
4367
4368                         pdata += 0x60;
4369
4370                         len = srvstr_push(dstart, flags2,
4371                                           pdata+4, dos_fname,
4372                                           PTR_DIFF(dend, pdata+4),
4373                                           STR_UNICODE);
4374                         SIVAL(pdata,0,len);
4375                         pdata += 4 + len;
4376                         data_size = PTR_DIFF(pdata,(*ppdata));
4377                         break;
4378                 }
4379                 case SMB_FILE_INTERNAL_INFORMATION:
4380
4381                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4382                         SBVAL(pdata, 0, file_index);
4383                         data_size = 8;
4384                         break;
4385
4386                 case SMB_FILE_ACCESS_INFORMATION:
4387                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4388                         SIVAL(pdata, 0, access_mask);
4389                         data_size = 4;
4390                         break;
4391
4392                 case SMB_FILE_NAME_INFORMATION:
4393                         /* Pathname with leading '\'. */
4394                         {
4395                                 size_t byte_len;
4396                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4397                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4398                                 SIVAL(pdata,0,byte_len);
4399                                 data_size = 4 + byte_len;
4400                                 break;
4401                         }
4402
4403                 case SMB_FILE_DISPOSITION_INFORMATION:
4404                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4405                         data_size = 1;
4406                         SCVAL(pdata,0,delete_pending);
4407                         break;
4408
4409                 case SMB_FILE_POSITION_INFORMATION:
4410                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4411                         data_size = 8;
4412                         SOFF_T(pdata,0,pos);
4413                         break;
4414
4415                 case SMB_FILE_MODE_INFORMATION:
4416                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4417                         SIVAL(pdata,0,mode);
4418                         data_size = 4;
4419                         break;
4420
4421                 case SMB_FILE_ALIGNMENT_INFORMATION:
4422                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4423                         SIVAL(pdata,0,0); /* No alignment needed. */
4424                         data_size = 4;
4425                         break;
4426
4427                 /*
4428                  * NT4 server just returns "invalid query" to this - if we try
4429                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
4430                  * want this. JRA.
4431                  */
4432                 /* The first statement above is false - verified using Thursby
4433                  * client against NT4 -- gcolley.
4434                  */
4435                 case SMB_QUERY_FILE_STREAM_INFO:
4436                 case SMB_FILE_STREAM_INFORMATION: {
4437                         unsigned int num_streams;
4438                         struct stream_struct *streams;
4439
4440                         DEBUG(10,("smbd_do_qfilepathinfo: "
4441                                   "SMB_FILE_STREAM_INFORMATION\n"));
4442
4443                         status = SMB_VFS_STREAMINFO(
4444                                 conn, fsp, fname, talloc_tos(),
4445                                 &num_streams, &streams);
4446
4447                         if (!NT_STATUS_IS_OK(status)) {
4448                                 DEBUG(10, ("could not get stream info: %s\n",
4449                                            nt_errstr(status)));
4450                                 return status;
4451                         }
4452
4453                         status = marshall_stream_info(num_streams, streams,
4454                                                       pdata, max_data_bytes,
4455                                                       &data_size);
4456
4457                         if (!NT_STATUS_IS_OK(status)) {
4458                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
4459                                            nt_errstr(status)));
4460                                 return status;
4461                         }
4462
4463                         TALLOC_FREE(streams);
4464
4465                         break;
4466                 }
4467                 case SMB_QUERY_COMPRESSION_INFO:
4468                 case SMB_FILE_COMPRESSION_INFORMATION:
4469                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4470                         SOFF_T(pdata,0,file_size);
4471                         SIVAL(pdata,8,0); /* ??? */
4472                         SIVAL(pdata,12,0); /* ??? */
4473                         data_size = 16;
4474                         break;
4475
4476                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4477                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4478                         put_long_date_timespec(pdata,create_time_ts);
4479                         put_long_date_timespec(pdata+8,atime_ts);
4480                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4481                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4482                         SOFF_T(pdata,32,allocation_size);
4483                         SOFF_T(pdata,40,file_size);
4484                         SIVAL(pdata,48,mode);
4485                         SIVAL(pdata,52,0); /* ??? */
4486                         data_size = 56;
4487                         break;
4488
4489                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4490                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4491                         SIVAL(pdata,0,mode);
4492                         SIVAL(pdata,4,0);
4493                         data_size = 8;
4494                         break;
4495
4496                 /*
4497                  * CIFS UNIX Extensions.
4498                  */
4499
4500                 case SMB_QUERY_FILE_UNIX_BASIC:
4501
4502                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4503                         data_size = PTR_DIFF(pdata,(*ppdata));
4504
4505                         {
4506                                 int i;
4507                                 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4508
4509                                 for (i=0; i<100; i++)
4510                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4511                                 DEBUG(4,("\n"));
4512                         }
4513
4514                         break;
4515
4516                 case SMB_QUERY_FILE_UNIX_INFO2:
4517
4518                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4519                         data_size = PTR_DIFF(pdata,(*ppdata));
4520
4521                         {
4522                                 int i;
4523                                 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4524
4525                                 for (i=0; i<100; i++)
4526                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4527                                 DEBUG(4,("\n"));
4528                         }
4529
4530                         break;
4531
4532                 case SMB_QUERY_FILE_UNIX_LINK:
4533                         {
4534                                 int len;
4535                                 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4536
4537                                 if (!buffer) {
4538                                         return NT_STATUS_NO_MEMORY;
4539                                 }
4540
4541                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4542 #ifdef S_ISLNK
4543                                 if(!S_ISLNK(sbuf.st_ex_mode)) {
4544                                         return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4545                                 }
4546 #else
4547                                 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4548 #endif
4549                                 len = SMB_VFS_READLINK(conn,fname,
4550                                                 buffer, PATH_MAX);
4551                                 if (len == -1) {
4552                                         return map_nt_error_from_unix(errno);
4553                                 }
4554                                 buffer[len] = 0;
4555                                 len = srvstr_push(dstart, flags2,
4556                                                   pdata, buffer,
4557                                                   PTR_DIFF(dend, pdata),
4558                                                   STR_TERMINATE);
4559                                 pdata += len;
4560                                 data_size = PTR_DIFF(pdata,(*ppdata));
4561
4562                                 break;
4563                         }
4564
4565 #if defined(HAVE_POSIX_ACLS)
4566                 case SMB_QUERY_POSIX_ACL:
4567                         {
4568                                 SMB_ACL_T file_acl = NULL;
4569                                 SMB_ACL_T def_acl = NULL;
4570                                 uint16 num_file_acls = 0;
4571                                 uint16 num_def_acls = 0;
4572
4573                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4574                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4575                                 } else {
4576                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4577                                 }
4578
4579                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4580                                         DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4581                                                 fname ));
4582                                         return NT_STATUS_NOT_IMPLEMENTED;
4583                                 }
4584
4585                                 if (S_ISDIR(sbuf.st_ex_mode)) {
4586                                         if (fsp && fsp->is_directory) {
4587                                                 def_acl =
4588                                                     SMB_VFS_SYS_ACL_GET_FILE(
4589                                                             conn,
4590                                                             fsp->fsp_name->base_name,
4591                                                             SMB_ACL_TYPE_DEFAULT);
4592                                         } else {
4593                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4594                                         }
4595                                         def_acl = free_empty_sys_acl(conn, def_acl);
4596                                 }
4597
4598                                 num_file_acls = count_acl_entries(conn, file_acl);
4599                                 num_def_acls = count_acl_entries(conn, def_acl);
4600
4601                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4602                                         DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4603                                                 data_size,
4604                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4605                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4606                                         if (file_acl) {
4607                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4608                                         }
4609                                         if (def_acl) {
4610                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4611                                         }
4612                                         return NT_STATUS_BUFFER_TOO_SMALL;
4613                                 }
4614
4615                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4616                                 SSVAL(pdata,2,num_file_acls);
4617                                 SSVAL(pdata,4,num_def_acls);
4618                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4619                                         if (file_acl) {
4620                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4621                                         }
4622                                         if (def_acl) {
4623                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4624                                         }
4625                                         return NT_STATUS_INTERNAL_ERROR;
4626                                 }
4627                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4628                                         if (file_acl) {
4629                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4630                                         }
4631                                         if (def_acl) {
4632                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4633                                         }
4634                                         return NT_STATUS_INTERNAL_ERROR;
4635                                 }
4636
4637                                 if (file_acl) {
4638                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4639                                 }
4640                                 if (def_acl) {
4641                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4642                                 }
4643                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4644                                 break;
4645                         }
4646 #endif
4647
4648
4649                 case SMB_QUERY_POSIX_LOCK:
4650                 {
4651                         uint64_t count;
4652                         uint64_t offset;
4653                         uint32 lock_pid;
4654                         enum brl_type lock_type;
4655
4656                         /* We need an open file with a real fd for this. */
4657                         if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4658                                 return NT_STATUS_INVALID_LEVEL;
4659                         }
4660
4661                         if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4662                                 return NT_STATUS_INVALID_PARAMETER;
4663                         }
4664
4665                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4666                                 case POSIX_LOCK_TYPE_READ:
4667                                         lock_type = READ_LOCK;
4668                                         break;
4669                                 case POSIX_LOCK_TYPE_WRITE:
4670                                         lock_type = WRITE_LOCK;
4671                                         break;
4672                                 case POSIX_LOCK_TYPE_UNLOCK:
4673                                 default:
4674                                         /* There's no point in asking for an unlock... */
4675                                         return NT_STATUS_INVALID_PARAMETER;
4676                         }
4677
4678                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4679 #if defined(HAVE_LONGLONG)
4680                         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4681                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4682                         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4683                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4684 #else /* HAVE_LONGLONG */
4685                         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4686                         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4687 #endif /* HAVE_LONGLONG */
4688
4689                         status = query_lock(fsp,
4690                                         &lock_pid,
4691                                         &count,
4692                                         &offset,
4693                                         &lock_type,
4694                                         POSIX_LOCK);
4695
4696                         if (ERROR_WAS_LOCK_DENIED(status)) {
4697                                 /* Here we need to report who has it locked... */
4698                                 data_size = POSIX_LOCK_DATA_SIZE;
4699
4700                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4701                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4702                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4703 #if defined(HAVE_LONGLONG)
4704                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4705                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4706                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4707                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4708 #else /* HAVE_LONGLONG */
4709                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4710                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4711 #endif /* HAVE_LONGLONG */
4712
4713                         } else if (NT_STATUS_IS_OK(status)) {
4714                                 /* For success we just return a copy of what we sent
4715                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4716                                 data_size = POSIX_LOCK_DATA_SIZE;
4717                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4718                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4719                         } else {
4720                                 return status;
4721                         }
4722                         break;
4723                 }
4724
4725                 default:
4726                         return NT_STATUS_INVALID_LEVEL;
4727         }
4728
4729         *pdata_size = data_size;
4730         return NT_STATUS_OK;
4731 }
4732
4733 /****************************************************************************
4734  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4735  file name or file id).
4736 ****************************************************************************/
4737
4738 static void call_trans2qfilepathinfo(connection_struct *conn,
4739                                      struct smb_request *req,
4740                                      unsigned int tran_call,
4741                                      char **pparams, int total_params,
4742                                      char **ppdata, int total_data,
4743                                      unsigned int max_data_bytes)
4744 {
4745         char *params = *pparams;
4746         char *pdata = *ppdata;
4747         uint16 info_level;
4748         unsigned int data_size = 0;
4749         unsigned int param_size = 2;
4750         struct smb_filename *smb_fname = NULL;
4751         bool delete_pending = False;
4752         struct timespec write_time_ts;
4753         files_struct *fsp = NULL;
4754         struct file_id fileid;
4755         struct ea_list *ea_list = NULL;
4756         int lock_data_count = 0;
4757         char *lock_data = NULL;
4758         bool ms_dfs_link = false;
4759         NTSTATUS status = NT_STATUS_OK;
4760
4761         if (!params) {
4762                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4763                 return;
4764         }
4765
4766         ZERO_STRUCT(write_time_ts);
4767
4768         if (tran_call == TRANSACT2_QFILEINFO) {
4769                 if (total_params < 4) {
4770                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4771                         return;
4772                 }
4773
4774                 if (IS_IPC(conn)) {
4775                         call_trans2qpipeinfo(conn, req, tran_call,
4776                                              pparams, total_params,
4777                                              ppdata, total_data,
4778                                              max_data_bytes);
4779                         return;
4780                 }
4781
4782                 fsp = file_fsp(req, SVAL(params,0));
4783                 info_level = SVAL(params,2);
4784
4785                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4786
4787                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4788                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4789                         return;
4790                 }
4791
4792                 /* Initial check for valid fsp ptr. */
4793                 if (!check_fsp_open(conn, req, fsp)) {
4794                         return;
4795                 }
4796
4797                 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4798                                            &smb_fname);
4799                 if (!NT_STATUS_IS_OK(status)) {
4800                         reply_nterror(req, status);
4801                         return;
4802                 }
4803
4804                 if(fsp->fake_file_handle) {
4805                         /*
4806                          * This is actually for the QUOTA_FAKE_FILE --metze
4807                          */
4808
4809                         /* We know this name is ok, it's already passed the checks. */
4810
4811                 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4812                         /*
4813                          * This is actually a QFILEINFO on a directory
4814                          * handle (returned from an NT SMB). NT5.0 seems
4815                          * to do this call. JRA.
4816                          */
4817
4818                         if (INFO_LEVEL_IS_UNIX(info_level)) {
4819                                 /* Always do lstat for UNIX calls. */
4820                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4821                                         DEBUG(3,("call_trans2qfilepathinfo: "
4822                                                  "SMB_VFS_LSTAT of %s failed "
4823                                                  "(%s)\n",
4824                                                  smb_fname_str_dbg(smb_fname),
4825                                                  strerror(errno)));
4826                                         reply_nterror(req,
4827                                                 map_nt_error_from_unix(errno));
4828                                         return;
4829                                 }
4830                         } else if (SMB_VFS_STAT(conn, smb_fname)) {
4831                                 DEBUG(3,("call_trans2qfilepathinfo: "
4832                                          "SMB_VFS_STAT of %s failed (%s)\n",
4833                                          smb_fname_str_dbg(smb_fname),
4834                                          strerror(errno)));
4835                                 reply_nterror(req,
4836                                         map_nt_error_from_unix(errno));
4837                                 return;
4838                         }
4839
4840                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4841                         get_file_infos(fileid, &delete_pending, &write_time_ts);
4842                 } else {
4843                         /*
4844                          * Original code - this is an open file.
4845                          */
4846                         if (!check_fsp(conn, req, fsp)) {
4847                                 return;
4848                         }
4849
4850                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4851                                 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4852                                           fsp->fnum, strerror(errno)));
4853                                 reply_nterror(req,
4854                                         map_nt_error_from_unix(errno));
4855                                 return;
4856                         }
4857                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4858                         get_file_infos(fileid, &delete_pending, &write_time_ts);
4859                 }
4860
4861         } else {
4862                 char *fname = NULL;
4863
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                 if (!NT_STATUS_IS_OK(status)) {
4893                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4894                                 reply_botherror(req,
4895                                                 NT_STATUS_PATH_NOT_COVERED,
4896                                                 ERRSRV, ERRbadpath);
4897                                 return;
4898                         }
4899                         reply_nterror(req, status);
4900                         return;
4901                 }
4902
4903                 /* If this is a stream, check if there is a delete_pending. */
4904                 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4905                     && is_ntfs_stream_smb_fname(smb_fname)) {
4906                         struct smb_filename *smb_fname_base = NULL;
4907
4908                         /* Create an smb_filename with stream_name == NULL. */
4909                         status =
4910                             create_synthetic_smb_fname(talloc_tos(),
4911                                                        smb_fname->base_name,
4912                                                        NULL, NULL,
4913                                                        &smb_fname_base);
4914                         if (!NT_STATUS_IS_OK(status)) {
4915                                 reply_nterror(req, status);
4916                                 return;
4917                         }
4918
4919                         if (INFO_LEVEL_IS_UNIX(info_level)) {
4920                                 /* Always do lstat for UNIX calls. */
4921                                 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4922                                         DEBUG(3,("call_trans2qfilepathinfo: "
4923                                                  "SMB_VFS_LSTAT of %s failed "
4924                                                  "(%s)\n",
4925                                                  smb_fname_str_dbg(smb_fname_base),
4926                                                  strerror(errno)));
4927                                         TALLOC_FREE(smb_fname_base);
4928                                         reply_nterror(req,
4929                                                 map_nt_error_from_unix(errno));
4930                                         return;
4931                                 }
4932                         } else {
4933                                 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4934                                         DEBUG(3,("call_trans2qfilepathinfo: "
4935                                                  "fileinfo of %s failed "
4936                                                  "(%s)\n",
4937                                                  smb_fname_str_dbg(smb_fname_base),
4938                                                  strerror(errno)));
4939                                         TALLOC_FREE(smb_fname_base);
4940                                         reply_nterror(req,
4941                                                 map_nt_error_from_unix(errno));
4942                                         return;
4943                                 }
4944                         }
4945
4946                         fileid = vfs_file_id_from_sbuf(conn,
4947                                                        &smb_fname_base->st);
4948                         TALLOC_FREE(smb_fname_base);
4949                         get_file_infos(fileid, &delete_pending, NULL);
4950                         if (delete_pending) {
4951                                 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4952                                 return;
4953                         }
4954                 }
4955
4956                 if (INFO_LEVEL_IS_UNIX(info_level)) {
4957                         /* Always do lstat for UNIX calls. */
4958                         if (SMB_VFS_LSTAT(conn, smb_fname)) {
4959                                 DEBUG(3,("call_trans2qfilepathinfo: "
4960                                          "SMB_VFS_LSTAT of %s failed (%s)\n",
4961                                          smb_fname_str_dbg(smb_fname),
4962                                          strerror(errno)));
4963                                 reply_nterror(req,
4964                                         map_nt_error_from_unix(errno));
4965                                 return;
4966                         }
4967
4968                 } else if (!VALID_STAT(smb_fname->st) &&
4969                            SMB_VFS_STAT(conn, smb_fname) &&
4970                            (info_level != SMB_INFO_IS_NAME_VALID)) {
4971                         ms_dfs_link = check_msdfs_link(conn,
4972                                                        smb_fname->base_name,
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 "
4995                  "total_data=%d\n", smb_fname_str_dbg(smb_fname),
4996                  fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4997
4998         /* Pull out any data sent here before we realloc. */
4999         switch (info_level) {
5000                 case SMB_INFO_QUERY_EAS_FROM_LIST:
5001                 {
5002                         /* Pull any EA list from the data portion. */
5003                         uint32 ea_size;
5004
5005                         if (total_data < 4) {
5006                                 reply_nterror(
5007                                         req, NT_STATUS_INVALID_PARAMETER);
5008                                 return;
5009                         }
5010                         ea_size = IVAL(pdata,0);
5011
5012                         if (total_data > 0 && ea_size != total_data) {
5013                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5014 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5015                                 reply_nterror(
5016                                         req, NT_STATUS_INVALID_PARAMETER);
5017                                 return;
5018                         }
5019
5020                         if (!lp_ea_support(SNUM(conn))) {
5021                                 reply_doserror(req, ERRDOS,
5022                                                ERReasnotsupported);
5023                                 return;
5024                         }
5025
5026                         /* Pull out the list of names. */
5027                         ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5028                         if (!ea_list) {
5029                                 reply_nterror(
5030                                         req, NT_STATUS_INVALID_PARAMETER);
5031                                 return;
5032                         }
5033                         break;
5034                 }
5035
5036                 case SMB_QUERY_POSIX_LOCK:
5037                 {
5038                         if (fsp == NULL || fsp->fh->fd == -1) {
5039                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5040                                 return;
5041                         }
5042
5043                         if (total_data != POSIX_LOCK_DATA_SIZE) {
5044                                 reply_nterror(
5045                                         req, NT_STATUS_INVALID_PARAMETER);
5046                                 return;
5047                         }
5048
5049                         /* Copy the lock range data. */
5050                         lock_data = (char *)TALLOC_MEMDUP(
5051                                 req, pdata, total_data);
5052                         if (!lock_data) {
5053                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5054                                 return;
5055                         }
5056                         lock_data_count = total_data;
5057                 }
5058                 default:
5059                         break;
5060         }
5061
5062         *pparams = (char *)SMB_REALLOC(*pparams,2);
5063         if (*pparams == NULL) {
5064                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5065                 return;
5066         }
5067         params = *pparams;
5068         SSVAL(params,0,0);
5069
5070         /*
5071          * draft-leach-cifs-v1-spec-02.txt
5072          * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5073          * says:
5074          *
5075          *  The requested information is placed in the Data portion of the
5076          *  transaction response. For the information levels greater than 0x100,
5077          *  the transaction response has 1 parameter word which should be
5078          *  ignored by the client.
5079          *
5080          * However Windows only follows this rule for the IS_NAME_VALID call.
5081          */
5082         switch (info_level) {
5083         case SMB_INFO_IS_NAME_VALID:
5084                 param_size = 0;
5085                 break;
5086         }
5087
5088         if ((info_level & 0xFF00) == 0xFF00) {
5089                 /*
5090                  * We use levels that start with 0xFF00
5091                  * internally to represent SMB2 specific levels
5092                  */
5093                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5094                 return;
5095         }
5096
5097         status = smbd_do_qfilepathinfo(conn, req, info_level,
5098                                        fsp, smb_fname,
5099                                        delete_pending, write_time_ts,
5100                                        ms_dfs_link, ea_list,
5101                                        lock_data_count, lock_data,
5102                                        req->flags2, max_data_bytes,
5103                                        ppdata, &data_size);
5104         if (!NT_STATUS_IS_OK(status)) {
5105                 reply_nterror(req, status);
5106                 return;
5107         }
5108
5109         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5110                             max_data_bytes);
5111
5112         return;
5113 }
5114
5115 /****************************************************************************
5116  Set a hard link (called by UNIX extensions and by NT rename with HARD link
5117  code.
5118 ****************************************************************************/
5119
5120 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5121                 connection_struct *conn,
5122                 const struct smb_filename *smb_fname_old,
5123                 const struct smb_filename *smb_fname_new)
5124 {
5125         char *oldname = NULL;
5126         char *newname = NULL;
5127         NTSTATUS status = NT_STATUS_OK;
5128
5129         /* source must already exist. */
5130         if (!VALID_STAT(smb_fname_old->st)) {
5131                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5132         }
5133
5134         /* Disallow if newname already exists. */
5135         if (VALID_STAT(smb_fname_new->st)) {
5136                 return NT_STATUS_OBJECT_NAME_COLLISION;
5137         }
5138
5139         /* No links from a directory. */
5140         if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5141                 return NT_STATUS_FILE_IS_A_DIRECTORY;
5142         }
5143
5144         status = get_full_smb_filename(ctx, smb_fname_new, &newname);
5145         if (!NT_STATUS_IS_OK(status)) {
5146                 goto out;
5147         }
5148         status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
5149         if (!NT_STATUS_IS_OK(status)) {
5150                 goto out;
5151         }
5152
5153         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
5154
5155         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
5156                 status = map_nt_error_from_unix(errno);
5157                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5158                                  nt_errstr(status), newname, oldname));
5159         }
5160  out:
5161         TALLOC_FREE(newname);
5162         TALLOC_FREE(oldname);
5163         return status;
5164 }
5165
5166 /****************************************************************************
5167  Deal with setting the time from any of the setfilepathinfo functions.
5168 ****************************************************************************/
5169
5170 NTSTATUS smb_set_file_time(connection_struct *conn,
5171                            files_struct *fsp,
5172                            const struct smb_filename *smb_fname,
5173                            struct smb_file_time *ft,
5174                            bool setting_write_time)
5175 {
5176         struct smb_filename *smb_fname_base = NULL;
5177         uint32 action =
5178                 FILE_NOTIFY_CHANGE_LAST_ACCESS
5179                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5180         NTSTATUS status;
5181
5182         if (!VALID_STAT(smb_fname->st)) {
5183                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5184         }
5185
5186         /* get some defaults (no modifications) if any info is zero or -1. */
5187         if (null_timespec(ft->atime)) {
5188                 ft->atime= smb_fname->st.st_ex_atime;
5189                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5190         }
5191
5192         if (null_timespec(ft->mtime)) {
5193                 ft->mtime = smb_fname->st.st_ex_mtime;
5194                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5195         }
5196
5197         if (!setting_write_time) {
5198                 /* ft->mtime comes from change time, not write time. */
5199                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5200         }
5201
5202         DEBUG(5,("smb_set_filetime: actime: %s\n ",
5203                 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5204         DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5205                 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5206         if (!null_timespec(ft->create_time)) {
5207                 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5208                    time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5209         }
5210
5211         /*
5212          * Try and set the times of this file if
5213          * they are different from the current values.
5214          */
5215
5216         {
5217                 struct timespec mts = smb_fname->st.st_ex_mtime;
5218                 struct timespec ats = smb_fname->st.st_ex_atime;
5219                 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5220                     (timespec_compare(&ft->mtime, &mts) == 0)) {
5221                         return NT_STATUS_OK;
5222                 }
5223         }
5224
5225         if (setting_write_time) {
5226                 /*
5227                  * This was a Windows setfileinfo on an open file.
5228                  * NT does this a lot. We also need to 
5229                  * set the time here, as it can be read by 
5230                  * FindFirst/FindNext and with the patch for bug #2045
5231                  * in smbd/fileio.c it ensures that this timestamp is
5232                  * kept sticky even after a write. We save the request
5233                  * away and will set it on file close and after a write. JRA.
5234                  */
5235
5236                 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5237                           time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5238
5239                 if (fsp != NULL) {
5240                         if (fsp->base_fsp) {
5241                                 set_sticky_write_time_fsp(fsp->base_fsp,
5242                                                           ft->mtime);
5243                         } else {
5244                                 set_sticky_write_time_fsp(fsp, ft->mtime);
5245                         }
5246                 } else {
5247                         set_sticky_write_time_path(
5248                                 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5249                                 ft->mtime);
5250                 }
5251         }
5252
5253         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5254
5255         /* Always call ntimes on the base, even if a stream was passed in. */
5256         status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5257                                             NULL, &smb_fname->st,
5258                                             &smb_fname_base);
5259         if (!NT_STATUS_IS_OK(status)) {
5260                 return status;
5261         }
5262
5263         if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5264                 TALLOC_FREE(smb_fname_base);
5265                 return map_nt_error_from_unix(errno);
5266         }
5267         TALLOC_FREE(smb_fname_base);
5268
5269         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5270                      smb_fname->base_name);
5271         return NT_STATUS_OK;
5272 }
5273
5274 /****************************************************************************
5275  Deal with setting the dosmode from any of the setfilepathinfo functions.
5276 ****************************************************************************/
5277
5278 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5279                                      const struct smb_filename *smb_fname,
5280                                      uint32 dosmode)
5281 {
5282         struct smb_filename *smb_fname_base = NULL;
5283         NTSTATUS status;
5284
5285         if (!VALID_STAT(smb_fname->st)) {
5286                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5287         }
5288
5289         /* Always operate on the base_name, even if a stream was passed in. */
5290         status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5291                                             NULL, &smb_fname->st,
5292                                             &smb_fname_base);
5293         if (!NT_STATUS_IS_OK(status)) {
5294                 return status;
5295         }
5296
5297         if (dosmode) {
5298                 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5299                         dosmode |= aDIR;
5300                 } else {
5301                         dosmode &= ~aDIR;
5302                 }
5303         }
5304
5305         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5306
5307         /* check the mode isn't different, before changing it */
5308         if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5309                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5310                           "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5311                           (unsigned int)dosmode));
5312
5313                 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5314                                     false)) {
5315                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5316                                  "%s failed (%s)\n",
5317                                  smb_fname_str_dbg(smb_fname_base),
5318                                  strerror(errno)));
5319                         status = map_nt_error_from_unix(errno);
5320                         goto out;
5321                 }
5322         }
5323         status = NT_STATUS_OK;
5324  out:
5325         TALLOC_FREE(smb_fname_base);
5326         return status;
5327 }
5328
5329 /****************************************************************************
5330  Deal with setting the size from any of the setfilepathinfo functions.
5331 ****************************************************************************/
5332
5333 static NTSTATUS smb_set_file_size(connection_struct *conn,
5334                                   struct smb_request *req,
5335                                   files_struct *fsp,
5336                                   const struct smb_filename *smb_fname,
5337                                   const SMB_STRUCT_STAT *psbuf,
5338                                   SMB_OFF_T size)
5339 {
5340         NTSTATUS status = NT_STATUS_OK;
5341         struct smb_filename *smb_fname_tmp = NULL;
5342         files_struct *new_fsp = NULL;
5343
5344         if (!VALID_STAT(*psbuf)) {
5345                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5346         }
5347
5348         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5349
5350         if (size == get_file_size_stat(psbuf)) {
5351                 return NT_STATUS_OK;
5352         }
5353
5354         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5355                   smb_fname_str_dbg(smb_fname), (double)size));
5356
5357         if (fsp && fsp->fh->fd != -1) {
5358                 /* Handle based call. */
5359                 if (vfs_set_filelen(fsp, size) == -1) {
5360                         return map_nt_error_from_unix(errno);
5361                 }
5362                 trigger_write_time_update_immediate(fsp);
5363                 return NT_STATUS_OK;
5364         }
5365
5366         status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5367         if (!NT_STATUS_IS_OK(status)) {
5368                 return status;
5369         }
5370
5371         smb_fname_tmp->st = *psbuf;
5372
5373         status = SMB_VFS_CREATE_FILE(
5374                 conn,                                   /* conn */
5375                 req,                                    /* req */
5376                 0,                                      /* root_dir_fid */
5377                 smb_fname_tmp,                          /* fname */
5378                 FILE_WRITE_ATTRIBUTES,                  /* access_mask */
5379                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5380                     FILE_SHARE_DELETE),
5381                 FILE_OPEN,                              /* create_disposition*/
5382                 0,                                      /* create_options */
5383                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
5384                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
5385                 0,                                      /* allocation_size */
5386                 NULL,                                   /* sd */
5387                 NULL,                                   /* ea_list */
5388                 &new_fsp,                               /* result */
5389                 NULL);                                  /* pinfo */
5390
5391         TALLOC_FREE(smb_fname_tmp);
5392
5393         if (!NT_STATUS_IS_OK(status)) {
5394                 /* NB. We check for open_was_deferred in the caller. */
5395                 return status;
5396         }
5397
5398         if (vfs_set_filelen(new_fsp, size) == -1) {
5399                 status = map_nt_error_from_unix(errno);
5400                 close_file(req, new_fsp,NORMAL_CLOSE);
5401                 return status;
5402         }
5403
5404         trigger_write_time_update_immediate(new_fsp);
5405         close_file(req, new_fsp,NORMAL_CLOSE);
5406         return NT_STATUS_OK;
5407 }
5408
5409 /****************************************************************************
5410  Deal with SMB_INFO_SET_EA.
5411 ****************************************************************************/
5412
5413 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5414                                 const char *pdata,
5415                                 int total_data,
5416                                 files_struct *fsp,
5417                                 const struct smb_filename *smb_fname)
5418 {
5419         struct ea_list *ea_list = NULL;
5420         TALLOC_CTX *ctx = NULL;
5421         NTSTATUS status = NT_STATUS_OK;
5422
5423         if (total_data < 10) {
5424
5425                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5426                    length. They seem to have no effect. Bug #3212. JRA */
5427
5428                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5429                         /* We're done. We only get EA info in this call. */
5430                         return NT_STATUS_OK;
5431                 }
5432
5433                 return NT_STATUS_INVALID_PARAMETER;
5434         }
5435
5436         if (IVAL(pdata,0) > total_data) {
5437                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5438                         IVAL(pdata,0), (unsigned int)total_data));
5439                 return NT_STATUS_INVALID_PARAMETER;
5440         }
5441
5442         ctx = talloc_tos();
5443         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5444         if (!ea_list) {
5445                 return NT_STATUS_INVALID_PARAMETER;
5446         }
5447         status = set_ea(conn, fsp, smb_fname, ea_list);
5448
5449         return status;
5450 }
5451
5452 /****************************************************************************
5453  Deal with SMB_SET_FILE_DISPOSITION_INFO.
5454 ****************************************************************************/
5455
5456 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5457                                 const char *pdata,
5458                                 int total_data,
5459                                 files_struct *fsp,
5460                                 const struct smb_filename *smb_fname)
5461 {
5462         NTSTATUS status = NT_STATUS_OK;
5463         bool delete_on_close;
5464         uint32 dosmode = 0;
5465
5466         if (total_data < 1) {
5467                 return NT_STATUS_INVALID_PARAMETER;
5468         }
5469
5470         if (fsp == NULL) {
5471                 return NT_STATUS_INVALID_HANDLE;
5472         }
5473
5474         delete_on_close = (CVAL(pdata,0) ? True : False);
5475         dosmode = dos_mode(conn, smb_fname);
5476
5477         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5478                 "delete_on_close = %u\n",
5479                 smb_fname_str_dbg(smb_fname),
5480                 (unsigned int)dosmode,
5481                 (unsigned int)delete_on_close ));
5482
5483         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5484  
5485         if (!NT_STATUS_IS_OK(status)) {
5486                 return status;
5487         }
5488
5489         /* The set is across all open files on this dev/inode pair. */
5490         if (!set_delete_on_close(fsp, delete_on_close,
5491                                  &conn->server_info->utok)) {
5492                 return NT_STATUS_ACCESS_DENIED;
5493         }
5494         return NT_STATUS_OK;
5495 }
5496
5497 /****************************************************************************
5498  Deal with SMB_FILE_POSITION_INFORMATION.
5499 ****************************************************************************/
5500
5501 static NTSTATUS smb_file_position_information(connection_struct *conn,
5502                                 const char *pdata,
5503                                 int total_data,
5504                                 files_struct *fsp)
5505 {
5506         uint64_t position_information;
5507
5508         if (total_data < 8) {
5509                 return NT_STATUS_INVALID_PARAMETER;
5510         }
5511
5512         if (fsp == NULL) {
5513                 /* Ignore on pathname based set. */
5514                 return NT_STATUS_OK;
5515         }
5516
5517         position_information = (uint64_t)IVAL(pdata,0);
5518 #ifdef LARGE_SMB_OFF_T
5519         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5520 #else /* LARGE_SMB_OFF_T */
5521         if (IVAL(pdata,4) != 0) {
5522                 /* more than 32 bits? */
5523                 return NT_STATUS_INVALID_PARAMETER;
5524         }
5525 #endif /* LARGE_SMB_OFF_T */
5526
5527         DEBUG(10,("smb_file_position_information: Set file position "
5528                   "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5529                   (double)position_information));
5530         fsp->fh->position_information = position_information;
5531         return NT_STATUS_OK;
5532 }
5533
5534 /****************************************************************************
5535  Deal with SMB_FILE_MODE_INFORMATION.
5536 ****************************************************************************/
5537
5538 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5539                                 const char *pdata,
5540                                 int total_data)
5541 {
5542         uint32 mode;
5543
5544         if (total_data < 4) {
5545                 return NT_STATUS_INVALID_PARAMETER;
5546         }
5547         mode = IVAL(pdata,0);
5548         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5549                 return NT_STATUS_INVALID_PARAMETER;
5550         }
5551         return NT_STATUS_OK;
5552 }
5553
5554 /****************************************************************************
5555  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5556 ****************************************************************************/
5557
5558 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5559                                        struct smb_request *req,
5560                                        const char *pdata,
5561                                        int total_data,
5562                                        const char *fname)
5563 {
5564         char *link_target = NULL;
5565         const char *newname = fname;
5566         NTSTATUS status = NT_STATUS_OK;
5567         TALLOC_CTX *ctx = talloc_tos();
5568
5569         /* Set a symbolic link. */
5570         /* Don't allow this if follow links is false. */
5571
5572         if (total_data == 0) {
5573                 return NT_STATUS_INVALID_PARAMETER;
5574         }
5575
5576         if (!lp_symlinks(SNUM(conn))) {
5577                 return NT_STATUS_ACCESS_DENIED;
5578         }
5579
5580         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5581                     total_data, STR_TERMINATE);
5582
5583         if (!link_target) {
5584                 return NT_STATUS_INVALID_PARAMETER;
5585         }
5586
5587         /* !widelinks forces the target path to be within the share. */
5588         /* This means we can interpret the target as a pathname. */
5589         if (!lp_widelinks(SNUM(conn))) {
5590                 char *rel_name = NULL;
5591                 char *last_dirp = NULL;
5592
5593                 if (*link_target == '/') {
5594                         /* No absolute paths allowed. */
5595                         return NT_STATUS_ACCESS_DENIED;
5596                 }
5597                 rel_name = talloc_strdup(ctx,newname);
5598                 if (!rel_name) {
5599                         return NT_STATUS_NO_MEMORY;
5600                 }
5601                 last_dirp = strrchr_m(rel_name, '/');
5602                 if (last_dirp) {
5603                         last_dirp[1] = '\0';
5604                 } else {
5605                         rel_name = talloc_strdup(ctx,"./");
5606                         if (!rel_name) {
5607                                 return NT_STATUS_NO_MEMORY;
5608                         }
5609                 }
5610                 rel_name = talloc_asprintf_append(rel_name,
5611                                 "%s",
5612                                 link_target);
5613                 if (!rel_name) {
5614                         return NT_STATUS_NO_MEMORY;
5615                 }
5616
5617                 status = check_name(conn, rel_name);
5618                 if (!NT_STATUS_IS_OK(status)) {
5619                         return status;
5620                 }
5621         }
5622
5623         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5624                         newname, link_target ));
5625
5626         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5627                 return map_nt_error_from_unix(errno);
5628         }
5629
5630         return NT_STATUS_OK;
5631 }
5632
5633 /****************************************************************************
5634  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5635 ****************************************************************************/
5636
5637 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5638                                         struct smb_request *req,
5639                                         const char *pdata, int total_data,
5640                                         const struct smb_filename *smb_fname_new)
5641 {
5642         char *oldname = NULL;
5643         struct smb_filename *smb_fname_old = NULL;
5644         TALLOC_CTX *ctx = talloc_tos();
5645         NTSTATUS status = NT_STATUS_OK;
5646
5647         /* Set a hard link. */
5648         if (total_data == 0) {
5649                 return NT_STATUS_INVALID_PARAMETER;
5650         }
5651
5652         srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5653                         total_data, STR_TERMINATE, &status);
5654         if (!NT_STATUS_IS_OK(status)) {
5655                 return status;
5656         }
5657
5658         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5659                 smb_fname_str_dbg(smb_fname_new), oldname));
5660
5661         status = filename_convert(ctx,
5662                                 conn,
5663                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
5664                                 oldname,
5665                                 &smb_fname_old);
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         struct smb_filename *smb_fname = NULL;
7352         files_struct *fsp = NULL;
7353         NTSTATUS status = NT_STATUS_OK;
7354         int data_return_size = 0;
7355
7356         if (!params) {
7357                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7358                 return;
7359         }
7360
7361         if (tran_call == TRANSACT2_SETFILEINFO) {
7362                 if (total_params < 4) {
7363                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7364                         return;
7365                 }
7366
7367                 fsp = file_fsp(req, SVAL(params,0));
7368                 /* Basic check for non-null fsp. */
7369                 if (!check_fsp_open(conn, req, fsp)) {
7370                         return;
7371                 }
7372                 info_level = SVAL(params,2);
7373
7374                 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7375                                            &smb_fname);
7376                 if (!NT_STATUS_IS_OK(status)) {
7377                         reply_nterror(req, status);
7378                         return;
7379                 }
7380
7381                 if(fsp->is_directory || fsp->fh->fd == -1) {
7382                         /*
7383                          * This is actually a SETFILEINFO on a directory
7384                          * handle (returned from an NT SMB). NT5.0 seems
7385                          * to do this call. JRA.
7386                          */
7387                         if (INFO_LEVEL_IS_UNIX(info_level)) {
7388                                 /* Always do lstat for UNIX calls. */
7389                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7390                                         DEBUG(3,("call_trans2setfilepathinfo: "
7391                                                  "SMB_VFS_LSTAT of %s failed "
7392                                                  "(%s)\n",
7393                                                  smb_fname_str_dbg(smb_fname),
7394                                                  strerror(errno)));
7395                                         reply_nterror(req, map_nt_error_from_unix(errno));
7396                                         return;
7397                                 }
7398                         } else {
7399                                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7400                                         DEBUG(3,("call_trans2setfilepathinfo: "
7401                                                  "fileinfo of %s failed (%s)\n",
7402                                                  smb_fname_str_dbg(smb_fname),
7403                                                  strerror(errno)));
7404                                         reply_nterror(req, map_nt_error_from_unix(errno));
7405                                         return;
7406                                 }
7407                         }
7408                 } else if (fsp->print_file) {
7409                         /*
7410                          * Doing a DELETE_ON_CLOSE should cancel a print job.
7411                          */
7412                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7413                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7414
7415                                 DEBUG(3,("call_trans2setfilepathinfo: "
7416                                          "Cancelling print job (%s)\n",
7417                                          fsp_str_dbg(fsp)));
7418
7419                                 SSVAL(params,0,0);
7420                                 send_trans2_replies(conn, req, params, 2,
7421                                                     *ppdata, 0,
7422                                                     max_data_bytes);
7423                                 return;
7424                         } else {
7425                                 reply_doserror(req, ERRDOS, ERRbadpath);
7426                                 return;
7427                         }
7428                 } else {
7429                         /*
7430                          * Original code - this is an open file.
7431                          */
7432                         if (!check_fsp(conn, req, fsp)) {
7433                                 return;
7434                         }
7435
7436                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7437                                 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7438                                          "of fnum %d failed (%s)\n", fsp->fnum,
7439                                          strerror(errno)));
7440                                 reply_nterror(req, map_nt_error_from_unix(errno));
7441                                 return;
7442                         }
7443                 }
7444         } else {
7445                 char *fname = NULL;
7446
7447                 /* set path info */
7448                 if (total_params < 7) {
7449                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7450                         return;
7451                 }
7452
7453                 info_level = SVAL(params,0);
7454                 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7455                                 total_params - 6, STR_TERMINATE,
7456                                 &status);
7457                 if (!NT_STATUS_IS_OK(status)) {
7458                         reply_nterror(req, status);
7459                         return;
7460                 }
7461
7462                 status = filename_convert(req, conn,
7463                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
7464                                          fname,
7465                                          &smb_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 "
7497                  "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7498                  fsp ? fsp->fnum : -1, info_level,total_data));
7499
7500         /* Realloc the parameter size */
7501         *pparams = (char *)SMB_REALLOC(*pparams,2);
7502         if (*pparams == NULL) {
7503                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7504                 return;
7505         }
7506         params = *pparams;
7507
7508         SSVAL(params,0,0);
7509
7510         status = smbd_do_setfilepathinfo(conn, req, req,
7511                                          info_level,
7512                                          fsp,
7513                                          smb_fname,
7514                                          ppdata, total_data,
7515                                          &data_return_size);
7516         if (!NT_STATUS_IS_OK(status)) {
7517                 if (open_was_deferred(req->mid)) {
7518                         /* We have re-scheduled this call. */
7519                         return;
7520                 }
7521                 if (blocking_lock_was_deferred(req->mid)) {
7522                         /* We have re-scheduled this call. */
7523                         return;
7524                 }
7525                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7526                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7527                                         ERRSRV, ERRbadpath);
7528                         return;
7529                 }
7530                 if (info_level == SMB_POSIX_PATH_OPEN) {
7531                         reply_openerror(req, status);
7532                         return;
7533                 }
7534
7535                 reply_nterror(req, status);
7536                 return;
7537         }
7538
7539         send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7540                             max_data_bytes);
7541
7542         return;
7543 }
7544
7545 /****************************************************************************
7546  Reply to a TRANS2_MKDIR (make directory with extended attributes).
7547 ****************************************************************************/
7548
7549 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7550                              char **pparams, int total_params,
7551                              char **ppdata, int total_data,
7552                              unsigned int max_data_bytes)
7553 {
7554         struct smb_filename *smb_dname = NULL;
7555         char *params = *pparams;
7556         char *pdata = *ppdata;
7557         char *directory = NULL;
7558         NTSTATUS status = NT_STATUS_OK;
7559         struct ea_list *ea_list = NULL;
7560         TALLOC_CTX *ctx = talloc_tos();
7561
7562         if (!CAN_WRITE(conn)) {
7563                 reply_doserror(req, ERRSRV, ERRaccess);
7564                 return;
7565         }
7566
7567         if (total_params < 5) {
7568                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7569                 return;
7570         }
7571
7572         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7573                         total_params - 4, STR_TERMINATE,
7574                         &status);
7575         if (!NT_STATUS_IS_OK(status)) {
7576                 reply_nterror(req, status);
7577                 return;
7578         }
7579
7580         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7581
7582         status = filename_convert(ctx,
7583                                 conn,
7584                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
7585                                 directory,
7586                                 &smb_dname);
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 }