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