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