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