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