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