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