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