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