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