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