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