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