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