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