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