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