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