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