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