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