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