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