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