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