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