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