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