Fix a const warning
[kai/samba.git] / source3 / smbd / trans2.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2007
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005-2007
7    Copyright (C) Steve French                   2005
8    Copyright (C) James Peach                    2006-2007
9
10    Extensively modified by Andrew Tridgell, 1995
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
31
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
34
35 static char *store_file_unix_basic(connection_struct *conn,
36                                 char *pdata,
37                                 files_struct *fsp,
38                                 const SMB_STRUCT_STAT *psbuf);
39
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41                                 char *pdata,
42                                 files_struct *fsp,
43                                 const SMB_STRUCT_STAT *psbuf);
44
45 /********************************************************************
46  Roundup a value to the nearest allocation roundup size boundary.
47  Only do this for Windows clients.
48 ********************************************************************/
49
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 {
52         uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53
54         /* Only roundup for Windows clients. */
55         enum remote_arch_types ra_type = get_remote_arch();
56         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57                 val = SMB_ROUNDUP(val,rval);
58         }
59         return val;
60 }
61
62 /********************************************************************
63  Given a stat buffer return the allocated size on disk, taking into
64  account sparse files.
65 ********************************************************************/
66
67 uint64_t get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
68 {
69         uint64_t 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 = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks;
77 #else
78         ret = (uint64_t)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(req, 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         uint64_t 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(req->cmd),
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(req->cmd),
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                         uint64_t 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) == (uint64_t)-1) {
2619                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2620                                 return;
2621                         }
2622
2623                         block_size = lp_block_size(snum);
2624                         if (bsize < block_size) {
2625                                 uint64_t factor = block_size/bsize;
2626                                 bsize = block_size;
2627                                 dsize /= factor;
2628                                 dfree /= factor;
2629                         }
2630                         if (bsize > block_size) {
2631                                 uint64_t 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                         uint64_t 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) == (uint64_t)-1) {
2739                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2740                                 return;
2741                         }
2742                         block_size = lp_block_size(snum);
2743                         if (bsize < block_size) {
2744                                 uint64_t factor = block_size/bsize;
2745                                 bsize = block_size;
2746                                 dsize /= factor;
2747                                 dfree /= factor;
2748                         }
2749                         if (bsize > block_size) {
2750                                 uint64_t 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                         uint64_t 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) == (uint64_t)-1) {
2772                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2773                                 return;
2774                         }
2775                         block_size = lp_block_size(snum);
2776                         if (bsize < block_size) {
2777                                 uint64_t factor = block_size/bsize;
2778                                 bsize = block_size;
2779                                 dsize /= factor;
2780                                 dfree /= factor;
2781                         }
2782                         if (bsize > block_size) {
2783                                 uint64_t 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 uint64_t or so
2815                  * Hard Quota Limit:    8 bytes seems like uint64_t 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,(uint64_t)0);
2864                         SBIG_UINT(pdata,8,(uint64_t)0);
2865                         SBIG_UINT(pdata,16,(uint64_t)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,((uint64_t)(
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                                   (uint64_t)conn->server_info->utok.uid);
3041                         SBIG_UINT(pdata, 16,
3042                                   (uint64_t)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                                           (uint64_t)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(req->cmd), 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(req, 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 (uint64_t)*/
3323                                 quotas.softlim = (uint64_t)IVAL(pdata,24);
3324 #ifdef LARGE_SMB_OFF_T
3325                                 quotas.softlim |= (((uint64_t)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 (uint64_t)*/
3339                                 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3340 #ifdef LARGE_SMB_OFF_T
3341                                 quotas.hardlim |= (((uint64_t)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         files_struct *fsp;
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         fsp = file_fsp(req, SVAL(params,0));
3770         if (!fsp_is_np(fsp)) {
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         uint64_t 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         char *lock_data = NULL;
3850         bool ms_dfs_link = false;
3851         TALLOC_CTX *ctx = talloc_tos();
3852
3853         if (!params) {
3854                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3855                 return;
3856         }
3857
3858         ZERO_STRUCT(sbuf);
3859         ZERO_STRUCT(write_time_ts);
3860
3861         if (tran_call == TRANSACT2_QFILEINFO) {
3862                 if (total_params < 4) {
3863                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3864                         return;
3865                 }
3866
3867                 if (IS_IPC(conn)) {
3868                         call_trans2qpipeinfo(conn, req, tran_call,
3869                                              pparams, total_params,
3870                                              ppdata, total_data,
3871                                              max_data_bytes);
3872                         return;
3873                 }
3874
3875                 fsp = file_fsp(req, SVAL(params,0));
3876                 info_level = SVAL(params,2);
3877
3878                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3879
3880                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3881                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3882                         return;
3883                 }
3884
3885                 /* Initial check for valid fsp ptr. */
3886                 if (!check_fsp_open(conn, req, fsp)) {
3887                         return;
3888                 }
3889
3890                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3891                 if (!fname) {
3892                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3893                         return;
3894                 }
3895
3896                 if(fsp->fake_file_handle) {
3897                         /*
3898                          * This is actually for the QUOTA_FAKE_FILE --metze
3899                          */
3900
3901                         /* We know this name is ok, it's already passed the checks. */
3902
3903                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3904                         /*
3905                          * This is actually a QFILEINFO on a directory
3906                          * handle (returned from an NT SMB). NT5.0 seems
3907                          * to do this call. JRA.
3908                          */
3909
3910                         if (INFO_LEVEL_IS_UNIX(info_level)) {
3911                                 /* Always do lstat for UNIX calls. */
3912                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3913                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3914                                         reply_unixerror(req,ERRDOS,ERRbadpath);
3915                                         return;
3916                                 }
3917                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3918                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3919                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3920                                 return;
3921                         }
3922
3923                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3924                         get_file_infos(fileid, &delete_pending, &write_time_ts);
3925                 } else {
3926                         /*
3927                          * Original code - this is an open file.
3928                          */
3929                         if (!check_fsp(conn, req, fsp)) {
3930                                 return;
3931                         }
3932
3933                         if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3934                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3935                                 reply_unixerror(req, ERRDOS, ERRbadfid);
3936                                 return;
3937                         }
3938                         pos = fsp->fh->position_information;
3939                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3940                         get_file_infos(fileid, &delete_pending, &write_time_ts);
3941                 }
3942
3943         } else {
3944                 NTSTATUS status = NT_STATUS_OK;
3945
3946                 /* qpathinfo */
3947                 if (total_params < 7) {
3948                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3949                         return;
3950                 }
3951
3952                 info_level = SVAL(params,0);
3953
3954                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3955
3956                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3957                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3958                         return;
3959                 }
3960
3961                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3962                                 total_params - 6,
3963                                 STR_TERMINATE, &status);
3964                 if (!NT_STATUS_IS_OK(status)) {
3965                         reply_nterror(req, status);
3966                         return;
3967                 }
3968
3969                 status = resolve_dfspath(ctx,
3970                                         conn,
3971                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
3972                                         fname,
3973                                         &fname);
3974                 if (!NT_STATUS_IS_OK(status)) {
3975                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3976                                 reply_botherror(req,
3977                                                 NT_STATUS_PATH_NOT_COVERED,
3978                                                 ERRSRV, ERRbadpath);
3979                         }
3980                         reply_nterror(req, status);
3981                         return;
3982                 }
3983
3984                 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3985                 if (!NT_STATUS_IS_OK(status)) {
3986                         reply_nterror(req, status);
3987                         return;
3988                 }
3989                 status = check_name(conn, fname);
3990                 if (!NT_STATUS_IS_OK(status)) {
3991                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3992                         reply_nterror(req, status);
3993                         return;
3994                 }
3995
3996                 if (INFO_LEVEL_IS_UNIX(info_level)) {
3997                         /* Always do lstat for UNIX calls. */
3998                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3999                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4000                                 reply_unixerror(req, ERRDOS, ERRbadpath);
4001                                 return;
4002                         }
4003
4004                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4005                         ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4006
4007                         if (!ms_dfs_link) {
4008                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4009                                 reply_unixerror(req, ERRDOS, ERRbadpath);
4010                                 return;
4011                         }
4012                 }
4013
4014                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4015                 get_file_infos(fileid, &delete_pending, &write_time_ts);
4016                 if (delete_pending) {
4017                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
4018                         return;
4019                 }
4020         }
4021
4022         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4023                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4024                 return;
4025         }
4026
4027         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4028                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4029
4030         p = strrchr_m(fname,'/');
4031         if (!p)
4032                 base_name = fname;
4033         else
4034                 base_name = p+1;
4035
4036         if (ms_dfs_link) {
4037                 mode = dos_mode_msdfs(conn,fname,&sbuf);
4038         } else {
4039                 mode = dos_mode(conn,fname,&sbuf);
4040         }
4041         if (!mode)
4042                 mode = FILE_ATTRIBUTE_NORMAL;
4043
4044         nlink = sbuf.st_nlink;
4045
4046         if (nlink && (mode&aDIR)) {
4047                 nlink = 1;
4048         }
4049
4050         if ((nlink > 0) && delete_pending) {
4051                 nlink -= 1;
4052         }
4053
4054         fullpathname = fname;
4055         if (!(mode & aDIR))
4056                 file_size = get_file_size(sbuf);
4057
4058         /* Pull out any data sent here before we realloc. */
4059         switch (info_level) {
4060                 case SMB_INFO_QUERY_EAS_FROM_LIST:
4061                 {
4062                         /* Pull any EA list from the data portion. */
4063                         uint32 ea_size;
4064
4065                         if (total_data < 4) {
4066                                 reply_nterror(
4067                                         req, NT_STATUS_INVALID_PARAMETER);
4068                                 return;
4069                         }
4070                         ea_size = IVAL(pdata,0);
4071
4072                         if (total_data > 0 && ea_size != total_data) {
4073                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4074 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4075                                 reply_nterror(
4076                                         req, NT_STATUS_INVALID_PARAMETER);
4077                                 return;
4078                         }
4079
4080                         if (!lp_ea_support(SNUM(conn))) {
4081                                 reply_doserror(req, ERRDOS,
4082                                                ERReasnotsupported);
4083                                 return;
4084                         }
4085
4086                         /* Pull out the list of names. */
4087                         ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4088                         if (!ea_list) {
4089                                 reply_nterror(
4090                                         req, NT_STATUS_INVALID_PARAMETER);
4091                                 return;
4092                         }
4093                         break;
4094                 }
4095
4096                 case SMB_QUERY_POSIX_LOCK:
4097                 {
4098                         if (fsp == NULL || fsp->fh->fd == -1) {
4099                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4100                                 return;
4101                         }
4102
4103                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4104                                 reply_nterror(
4105                                         req, NT_STATUS_INVALID_PARAMETER);
4106                                 return;
4107                         }
4108
4109                         /* Copy the lock range data. */
4110                         lock_data = (char *)TALLOC_MEMDUP(
4111                                 ctx, pdata, total_data);
4112                         if (!lock_data) {
4113                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4114                                 return;
4115                         }
4116                 }
4117                 default:
4118                         break;
4119         }
4120
4121         *pparams = (char *)SMB_REALLOC(*pparams,2);
4122         if (*pparams == NULL) {
4123                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4124                 return;
4125         }
4126         params = *pparams;
4127         SSVAL(params,0,0);
4128         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4129         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4130         if (*ppdata == NULL ) {
4131                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4132                 return;
4133         }
4134         pdata = *ppdata;
4135         dstart = pdata;
4136         dend = dstart + data_size - 1;
4137
4138         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4139         mtime_ts = get_mtimespec(&sbuf);
4140         atime_ts = get_atimespec(&sbuf);
4141
4142         allocation_size = get_allocation_size(conn,fsp,&sbuf);
4143
4144         if (!fsp) {
4145                 /* Do we have this path open ? */
4146                 files_struct *fsp1;
4147                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4148                 fsp1 = file_find_di_first(fileid);
4149                 if (fsp1 && fsp1->initial_allocation_size) {
4150                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4151                 }
4152         }
4153
4154         if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4155                 mtime_ts = write_time_ts;
4156         }
4157
4158         if (lp_dos_filetime_resolution(SNUM(conn))) {
4159                 dos_filetime_timespec(&create_time_ts);
4160                 dos_filetime_timespec(&mtime_ts);
4161                 dos_filetime_timespec(&atime_ts);
4162         }
4163
4164         create_time = convert_timespec_to_time_t(create_time_ts);
4165         mtime = convert_timespec_to_time_t(mtime_ts);
4166         atime = convert_timespec_to_time_t(atime_ts);
4167
4168         /* NT expects the name to be in an exact form of the *full*
4169            filename. See the trans2 torture test */
4170         if (ISDOT(base_name)) {
4171                 dos_fname = talloc_strdup(ctx, "\\");
4172                 if (!dos_fname) {
4173                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4174                         return;
4175                 }
4176         } else {
4177                 dos_fname = talloc_asprintf(ctx,
4178                                 "\\%s",
4179                                 fname);
4180                 if (!dos_fname) {
4181                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4182                         return;
4183                 }
4184                 string_replace(dos_fname, '/', '\\');
4185         }
4186
4187         switch (info_level) {
4188                 case SMB_INFO_STANDARD:
4189                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4190                         data_size = 22;
4191                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4192                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4193                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4194                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
4195                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4196                         SSVAL(pdata,l1_attrFile,mode);
4197                         break;
4198
4199                 case SMB_INFO_QUERY_EA_SIZE:
4200                 {
4201                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4202                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4203                         data_size = 26;
4204                         srv_put_dos_date2(pdata,0,create_time);
4205                         srv_put_dos_date2(pdata,4,atime);
4206                         srv_put_dos_date2(pdata,8,mtime); /* write time */
4207                         SIVAL(pdata,12,(uint32)file_size);
4208                         SIVAL(pdata,16,(uint32)allocation_size);
4209                         SSVAL(pdata,20,mode);
4210                         SIVAL(pdata,22,ea_size);
4211                         break;
4212                 }
4213
4214                 case SMB_INFO_IS_NAME_VALID:
4215                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4216                         if (tran_call == TRANSACT2_QFILEINFO) {
4217                                 /* os/2 needs this ? really ?*/
4218                                 reply_doserror(req, ERRDOS, ERRbadfunc);
4219                                 return;
4220                         }
4221                         data_size = 0;
4222                         param_size = 0;
4223                         break;
4224
4225                 case SMB_INFO_QUERY_EAS_FROM_LIST:
4226                 {
4227                         size_t total_ea_len = 0;
4228                         struct ea_list *ea_file_list = NULL;
4229
4230                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4231
4232                         ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4233                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4234
4235                         if (!ea_list || (total_ea_len > data_size)) {
4236                                 data_size = 4;
4237                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4238                                 break;
4239                         }
4240
4241                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4242                         break;
4243                 }
4244
4245                 case SMB_INFO_QUERY_ALL_EAS:
4246                 {
4247                         /* We have data_size bytes to put EA's into. */
4248                         size_t total_ea_len = 0;
4249
4250                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4251
4252                         ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4253                         if (!ea_list || (total_ea_len > data_size)) {
4254                                 data_size = 4;
4255                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4256                                 break;
4257                         }
4258
4259                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4260                         break;
4261                 }
4262
4263                 case SMB_FILE_BASIC_INFORMATION:
4264                 case SMB_QUERY_FILE_BASIC_INFO:
4265
4266                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4267                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4268                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4269                         } else {
4270                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4271                                 data_size = 40;
4272                                 SIVAL(pdata,36,0);
4273                         }
4274                         put_long_date_timespec(pdata,create_time_ts);
4275                         put_long_date_timespec(pdata+8,atime_ts);
4276                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4277                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4278                         SIVAL(pdata,32,mode);
4279
4280                         DEBUG(5,("SMB_QFBI - "));
4281                         DEBUG(5,("create: %s ", ctime(&create_time)));
4282                         DEBUG(5,("access: %s ", ctime(&atime)));
4283                         DEBUG(5,("write: %s ", ctime(&mtime)));
4284                         DEBUG(5,("change: %s ", ctime(&mtime)));
4285                         DEBUG(5,("mode: %x\n", mode));
4286                         break;
4287
4288                 case SMB_FILE_STANDARD_INFORMATION:
4289                 case SMB_QUERY_FILE_STANDARD_INFO:
4290
4291                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4292                         data_size = 24;
4293                         SOFF_T(pdata,0,allocation_size);
4294                         SOFF_T(pdata,8,file_size);
4295                         SIVAL(pdata,16,nlink);
4296                         SCVAL(pdata,20,delete_pending?1:0);
4297                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4298                         SSVAL(pdata,22,0); /* Padding. */
4299                         break;
4300
4301                 case SMB_FILE_EA_INFORMATION:
4302                 case SMB_QUERY_FILE_EA_INFO:
4303                 {
4304                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4305                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4306                         data_size = 4;
4307                         SIVAL(pdata,0,ea_size);
4308                         break;
4309                 }
4310
4311                 /* Get the 8.3 name - used if NT SMB was negotiated. */
4312                 case SMB_QUERY_FILE_ALT_NAME_INFO:
4313                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4314                 {
4315                         char mangled_name[13];
4316                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4317                         if (!name_to_8_3(base_name,mangled_name,
4318                                                 True,conn->params)) {
4319                                 reply_nterror(
4320                                         req,
4321                                         NT_STATUS_NO_MEMORY);
4322                         }
4323                         len = srvstr_push(dstart, req->flags2,
4324                                           pdata+4, mangled_name,
4325                                           PTR_DIFF(dend, pdata+4),
4326                                           STR_UNICODE);
4327                         data_size = 4 + len;
4328                         SIVAL(pdata,0,len);
4329                         break;
4330                 }
4331
4332                 case SMB_QUERY_FILE_NAME_INFO:
4333                         /*
4334                           this must be *exactly* right for ACLs on mapped drives to work
4335                          */
4336                         len = srvstr_push(dstart, req->flags2,
4337                                           pdata+4, dos_fname,
4338                                           PTR_DIFF(dend, pdata+4),
4339                                           STR_UNICODE);
4340                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4341                         data_size = 4 + len;
4342                         SIVAL(pdata,0,len);
4343                         break;
4344
4345                 case SMB_FILE_ALLOCATION_INFORMATION:
4346                 case SMB_QUERY_FILE_ALLOCATION_INFO:
4347                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4348                         data_size = 8;
4349                         SOFF_T(pdata,0,allocation_size);
4350                         break;
4351
4352                 case SMB_FILE_END_OF_FILE_INFORMATION:
4353                 case SMB_QUERY_FILE_END_OF_FILEINFO:
4354                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4355                         data_size = 8;
4356                         SOFF_T(pdata,0,file_size);
4357                         break;
4358
4359                 case SMB_QUERY_FILE_ALL_INFO:
4360                 case SMB_FILE_ALL_INFORMATION:
4361                 {
4362                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4363                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4364                         put_long_date_timespec(pdata,create_time_ts);
4365                         put_long_date_timespec(pdata+8,atime_ts);
4366                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4367                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4368                         SIVAL(pdata,32,mode);
4369                         SIVAL(pdata,36,0); /* padding. */
4370                         pdata += 40;
4371                         SOFF_T(pdata,0,allocation_size);
4372                         SOFF_T(pdata,8,file_size);
4373                         SIVAL(pdata,16,nlink);
4374                         SCVAL(pdata,20,delete_pending);
4375                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4376                         SSVAL(pdata,22,0);
4377                         pdata += 24;
4378                         SIVAL(pdata,0,ea_size);
4379                         pdata += 4; /* EA info */
4380                         len = srvstr_push(dstart, req->flags2,
4381                                           pdata+4, dos_fname,
4382                                           PTR_DIFF(dend, pdata+4),
4383                                           STR_UNICODE);
4384                         SIVAL(pdata,0,len);
4385                         pdata += 4 + len;
4386                         data_size = PTR_DIFF(pdata,(*ppdata));
4387                         break;
4388                 }
4389                 case SMB_FILE_INTERNAL_INFORMATION:
4390                         /* This should be an index number - looks like
4391                            dev/ino to me :-) 
4392
4393                            I think this causes us to fail the IFSKIT
4394                            BasicFileInformationTest. -tpot */
4395
4396                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4397                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4398                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4399                         data_size = 8;
4400                         break;
4401
4402                 case SMB_FILE_ACCESS_INFORMATION:
4403                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4404                         if (fsp) {
4405                                 SIVAL(pdata,0,fsp->access_mask);
4406                         } else {
4407                                 /* GENERIC_EXECUTE mapping from Windows */
4408                                 SIVAL(pdata,0,0x12019F);
4409                         }
4410                         data_size = 4;
4411                         break;
4412
4413                 case SMB_FILE_NAME_INFORMATION:
4414                         /* Pathname with leading '\'. */
4415                         {
4416                                 size_t byte_len;
4417                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4418                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4419                                 SIVAL(pdata,0,byte_len);
4420                                 data_size = 4 + byte_len;
4421                                 break;
4422                         }
4423
4424                 case SMB_FILE_DISPOSITION_INFORMATION:
4425                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4426                         data_size = 1;
4427                         SCVAL(pdata,0,delete_pending);
4428                         break;
4429
4430                 case SMB_FILE_POSITION_INFORMATION:
4431                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4432                         data_size = 8;
4433                         SOFF_T(pdata,0,pos);
4434                         break;
4435
4436                 case SMB_FILE_MODE_INFORMATION:
4437                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4438                         SIVAL(pdata,0,mode);
4439                         data_size = 4;
4440                         break;
4441
4442                 case SMB_FILE_ALIGNMENT_INFORMATION:
4443                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4444                         SIVAL(pdata,0,0); /* No alignment needed. */
4445                         data_size = 4;
4446                         break;
4447
4448                 /*
4449                  * NT4 server just returns "invalid query" to this - if we try
4450                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
4451                  * want this. JRA.
4452                  */
4453                 /* The first statement above is false - verified using Thursby
4454                  * client against NT4 -- gcolley.
4455                  */
4456                 case SMB_QUERY_FILE_STREAM_INFO:
4457                 case SMB_FILE_STREAM_INFORMATION: {
4458                         unsigned int num_streams;
4459                         struct stream_struct *streams;
4460                         NTSTATUS status;
4461
4462                         DEBUG(10,("call_trans2qfilepathinfo: "
4463                                   "SMB_FILE_STREAM_INFORMATION\n"));
4464
4465                         status = SMB_VFS_STREAMINFO(
4466                                 conn, fsp, fname, talloc_tos(),
4467                                 &num_streams, &streams);
4468
4469                         if (!NT_STATUS_IS_OK(status)) {
4470                                 DEBUG(10, ("could not get stream info: %s\n",
4471                                            nt_errstr(status)));
4472                                 reply_nterror(req, status);
4473                                 return;
4474                         }
4475
4476                         status = marshall_stream_info(num_streams, streams,
4477                                                       pdata, max_data_bytes,
4478                                                       &data_size);
4479
4480                         if (!NT_STATUS_IS_OK(status)) {
4481                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
4482                                            nt_errstr(status)));
4483                                 reply_nterror(req, status);
4484                                 return;
4485                         }
4486
4487                         TALLOC_FREE(streams);
4488
4489                         break;
4490                 }
4491                 case SMB_QUERY_COMPRESSION_INFO:
4492                 case SMB_FILE_COMPRESSION_INFORMATION:
4493                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4494                         SOFF_T(pdata,0,file_size);
4495                         SIVAL(pdata,8,0); /* ??? */
4496                         SIVAL(pdata,12,0); /* ??? */
4497                         data_size = 16;
4498                         break;
4499
4500                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4501                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4502                         put_long_date_timespec(pdata,create_time_ts);
4503                         put_long_date_timespec(pdata+8,atime_ts);
4504                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4505                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4506                         SOFF_T(pdata,32,allocation_size);
4507                         SOFF_T(pdata,40,file_size);
4508                         SIVAL(pdata,48,mode);
4509                         SIVAL(pdata,52,0); /* ??? */
4510                         data_size = 56;
4511                         break;
4512
4513                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4514                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4515                         SIVAL(pdata,0,mode);
4516                         SIVAL(pdata,4,0);
4517                         data_size = 8;
4518                         break;
4519
4520                 /*
4521                  * CIFS UNIX Extensions.
4522                  */
4523
4524                 case SMB_QUERY_FILE_UNIX_BASIC:
4525
4526                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4527                         data_size = PTR_DIFF(pdata,(*ppdata));
4528
4529                         {
4530                                 int i;
4531                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4532
4533                                 for (i=0; i<100; i++)
4534                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4535                                 DEBUG(4,("\n"));
4536                         }
4537
4538                         break;
4539
4540                 case SMB_QUERY_FILE_UNIX_INFO2:
4541
4542                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4543                         data_size = PTR_DIFF(pdata,(*ppdata));
4544
4545                         {
4546                                 int i;
4547                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4548
4549                                 for (i=0; i<100; i++)
4550                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4551                                 DEBUG(4,("\n"));
4552                         }
4553
4554                         break;
4555
4556                 case SMB_QUERY_FILE_UNIX_LINK:
4557                         {
4558                                 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4559
4560                                 if (!buffer) {
4561                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4562                                         return;
4563                                 }
4564
4565                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4566 #ifdef S_ISLNK
4567                                 if(!S_ISLNK(sbuf.st_mode)) {
4568                                         reply_unixerror(req, ERRSRV,
4569                                                         ERRbadlink);
4570                                         return;
4571                                 }
4572 #else
4573                                 reply_unixerror(req, ERRDOS, ERRbadlink);
4574                                 return;
4575 #endif
4576                                 len = SMB_VFS_READLINK(conn,fullpathname,
4577                                                 buffer, PATH_MAX);
4578                                 if (len == -1) {
4579                                         reply_unixerror(req, ERRDOS,
4580                                                         ERRnoaccess);
4581                                         return;
4582                                 }
4583                                 buffer[len] = 0;
4584                                 len = srvstr_push(dstart, req->flags2,
4585                                                   pdata, buffer,
4586                                                   PTR_DIFF(dend, pdata),
4587                                                   STR_TERMINATE);
4588                                 pdata += len;
4589                                 data_size = PTR_DIFF(pdata,(*ppdata));
4590
4591                                 break;
4592                         }
4593
4594 #if defined(HAVE_POSIX_ACLS)
4595                 case SMB_QUERY_POSIX_ACL:
4596                         {
4597                                 SMB_ACL_T file_acl = NULL;
4598                                 SMB_ACL_T def_acl = NULL;
4599                                 uint16 num_file_acls = 0;
4600                                 uint16 num_def_acls = 0;
4601
4602                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4603                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4604                                 } else {
4605                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4606                                 }
4607
4608                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4609                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4610                                                 fname ));
4611                                         reply_nterror(
4612                                                 req,
4613                                                 NT_STATUS_NOT_IMPLEMENTED);
4614                                         return;
4615                                 }
4616
4617                                 if (S_ISDIR(sbuf.st_mode)) {
4618                                         if (fsp && fsp->is_directory) {
4619                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4620                                         } else {
4621                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4622                                         }
4623                                         def_acl = free_empty_sys_acl(conn, def_acl);
4624                                 }
4625
4626                                 num_file_acls = count_acl_entries(conn, file_acl);
4627                                 num_def_acls = count_acl_entries(conn, def_acl);
4628
4629                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4630                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4631                                                 data_size,
4632                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4633                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4634                                         if (file_acl) {
4635                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4636                                         }
4637                                         if (def_acl) {
4638                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4639                                         }
4640                                         reply_nterror(
4641                                                 req,
4642                                                 NT_STATUS_BUFFER_TOO_SMALL);
4643                                         return;
4644                                 }
4645
4646                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4647                                 SSVAL(pdata,2,num_file_acls);
4648                                 SSVAL(pdata,4,num_def_acls);
4649                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4650                                         if (file_acl) {
4651                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4652                                         }
4653                                         if (def_acl) {
4654                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4655                                         }
4656                                         reply_nterror(
4657                                                 req, NT_STATUS_INTERNAL_ERROR);
4658                                         return;
4659                                 }
4660                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4661                                         if (file_acl) {
4662                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4663                                         }
4664                                         if (def_acl) {
4665                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4666                                         }
4667                                         reply_nterror(
4668                                                 req,
4669                                                 NT_STATUS_INTERNAL_ERROR);
4670                                         return;
4671                                 }
4672
4673                                 if (file_acl) {
4674                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4675                                 }
4676                                 if (def_acl) {
4677                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4678                                 }
4679                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4680                                 break;
4681                         }
4682 #endif
4683
4684
4685                 case SMB_QUERY_POSIX_LOCK:
4686                 {
4687                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4688                         uint64_t count;
4689                         uint64_t offset;
4690                         uint32 lock_pid;
4691                         enum brl_type lock_type;
4692
4693                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4694                                 reply_nterror(
4695                                         req, NT_STATUS_INVALID_PARAMETER);
4696                                 return;
4697                         }
4698
4699                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4700                                 case POSIX_LOCK_TYPE_READ:
4701                                         lock_type = READ_LOCK;
4702                                         break;
4703                                 case POSIX_LOCK_TYPE_WRITE:
4704                                         lock_type = WRITE_LOCK;
4705                                         break;
4706                                 case POSIX_LOCK_TYPE_UNLOCK:
4707                                 default:
4708                                         /* There's no point in asking for an unlock... */
4709                                         reply_nterror(
4710                                                 req,
4711                                                 NT_STATUS_INVALID_PARAMETER);
4712                                         return;
4713                         }
4714
4715                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4716 #if defined(HAVE_LONGLONG)
4717                         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4718                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4719                         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4720                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4721 #else /* HAVE_LONGLONG */
4722                         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4723                         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4724 #endif /* HAVE_LONGLONG */
4725
4726                         status = query_lock(fsp,
4727                                         &lock_pid,
4728                                         &count,
4729                                         &offset,
4730                                         &lock_type,
4731                                         POSIX_LOCK);
4732
4733                         if (ERROR_WAS_LOCK_DENIED(status)) {
4734                                 /* Here we need to report who has it locked... */
4735                                 data_size = POSIX_LOCK_DATA_SIZE;
4736
4737                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4738                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4739                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4740 #if defined(HAVE_LONGLONG)
4741                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4742                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4743                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4744                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4745 #else /* HAVE_LONGLONG */
4746                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4747                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4748 #endif /* HAVE_LONGLONG */
4749
4750                         } else if (NT_STATUS_IS_OK(status)) {
4751                                 /* For success we just return a copy of what we sent
4752                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4753                                 data_size = POSIX_LOCK_DATA_SIZE;
4754                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4755                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4756                         } else {
4757                                 reply_nterror(req, status);
4758                                 return;
4759                         }
4760                         break;
4761                 }
4762
4763                 default:
4764                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4765                         return;
4766         }
4767
4768         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4769                             max_data_bytes);
4770
4771         return;
4772 }
4773
4774 /****************************************************************************
4775  Set a hard link (called by UNIX extensions and by NT rename with HARD link
4776  code.
4777 ****************************************************************************/
4778
4779 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4780                 connection_struct *conn,
4781                 const char *oldname_in,
4782                 const char *newname_in)
4783 {
4784         SMB_STRUCT_STAT sbuf1, sbuf2;
4785         char *last_component_oldname = NULL;
4786         char *last_component_newname = NULL;
4787         char *oldname = NULL;
4788         char *newname = NULL;
4789         NTSTATUS status = NT_STATUS_OK;
4790
4791         ZERO_STRUCT(sbuf1);
4792         ZERO_STRUCT(sbuf2);
4793
4794         status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4795                         &last_component_oldname, &sbuf1);
4796         if (!NT_STATUS_IS_OK(status)) {
4797                 return status;
4798         }
4799
4800         status = check_name(conn, oldname);
4801         if (!NT_STATUS_IS_OK(status)) {
4802                 return status;
4803         }
4804
4805         /* source must already exist. */
4806         if (!VALID_STAT(sbuf1)) {
4807                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4808         }
4809
4810         status = unix_convert(ctx, conn, newname_in, False, &newname,
4811                         &last_component_newname, &sbuf2);
4812         if (!NT_STATUS_IS_OK(status)) {
4813                 return status;
4814         }
4815
4816         status = check_name(conn, newname);
4817         if (!NT_STATUS_IS_OK(status)) {
4818                 return status;
4819         }
4820
4821         /* Disallow if newname already exists. */
4822         if (VALID_STAT(sbuf2)) {
4823                 return NT_STATUS_OBJECT_NAME_COLLISION;
4824         }
4825
4826         /* No links from a directory. */
4827         if (S_ISDIR(sbuf1.st_mode)) {
4828                 return NT_STATUS_FILE_IS_A_DIRECTORY;
4829         }
4830
4831         /* Ensure this is within the share. */
4832         status = check_reduced_name(conn, oldname);
4833         if (!NT_STATUS_IS_OK(status)) {
4834                 return status;
4835         }
4836
4837         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4838
4839         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4840                 status = map_nt_error_from_unix(errno);
4841                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4842                                 nt_errstr(status), newname, oldname));
4843         }
4844
4845         return status;
4846 }
4847
4848 /****************************************************************************
4849  Deal with setting the time from any of the setfilepathinfo functions.
4850 ****************************************************************************/
4851
4852 NTSTATUS smb_set_file_time(connection_struct *conn,
4853                            files_struct *fsp,
4854                            const char *fname,
4855                            const SMB_STRUCT_STAT *psbuf,
4856                            struct timespec ts[2],
4857                            bool setting_write_time)
4858 {
4859         uint32 action =
4860                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4861                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4862
4863         if (!VALID_STAT(*psbuf)) {
4864                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4865         }
4866
4867         /* get some defaults (no modifications) if any info is zero or -1. */
4868         if (null_timespec(ts[0])) {
4869                 ts[0] = get_atimespec(psbuf);
4870                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4871         }
4872
4873         if (null_timespec(ts[1])) {
4874                 ts[1] = get_mtimespec(psbuf);
4875                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4876         }
4877
4878         if (!setting_write_time) {
4879                 /* ts[1] comes from change time, not write time. */
4880                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4881         }
4882
4883         DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4884         DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4885
4886         /*
4887          * Try and set the times of this file if
4888          * they are different from the current values.
4889          */
4890
4891         {
4892                 struct timespec mts = get_mtimespec(psbuf);
4893                 struct timespec ats = get_atimespec(psbuf);
4894                 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4895                         return NT_STATUS_OK;
4896                 }
4897         }
4898
4899         if (setting_write_time) {
4900                 /*
4901                  * This was a setfileinfo on an open file.
4902                  * NT does this a lot. We also need to 
4903                  * set the time here, as it can be read by 
4904                  * FindFirst/FindNext and with the patch for bug #2045
4905                  * in smbd/fileio.c it ensures that this timestamp is
4906                  * kept sticky even after a write. We save the request
4907                  * away and will set it on file close and after a write. JRA.
4908                  */
4909
4910                 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4911                           time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4912
4913                 if (fsp != NULL) {
4914                         set_sticky_write_time_fsp(fsp, ts[1]);
4915                 } else {
4916                         set_sticky_write_time_path(conn, fname,
4917                                             vfs_file_id_from_sbuf(conn, psbuf),
4918                                             ts[1]);
4919                 }
4920         }
4921
4922         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4923
4924         if(file_ntimes(conn, fname, ts)!=0) {
4925                 return map_nt_error_from_unix(errno);
4926         }
4927         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4928
4929         return NT_STATUS_OK;
4930 }
4931
4932 /****************************************************************************
4933  Deal with setting the dosmode from any of the setfilepathinfo functions.
4934 ****************************************************************************/
4935
4936 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4937                                 const char *fname,
4938                                 SMB_STRUCT_STAT *psbuf,
4939                                 uint32 dosmode)
4940 {
4941         if (!VALID_STAT(*psbuf)) {
4942                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4943         }
4944
4945         if (dosmode) {
4946                 if (S_ISDIR(psbuf->st_mode)) {
4947                         dosmode |= aDIR;
4948                 } else {
4949                         dosmode &= ~aDIR;
4950                 }
4951         }
4952
4953         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4954
4955         /* check the mode isn't different, before changing it */
4956         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4957
4958                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4959                                         fname, (unsigned int)dosmode ));
4960
4961                 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4962                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4963                                                 fname, strerror(errno)));
4964                         return map_nt_error_from_unix(errno);
4965                 }
4966         }
4967         return NT_STATUS_OK;
4968 }
4969
4970 /****************************************************************************
4971  Deal with setting the size from any of the setfilepathinfo functions.
4972 ****************************************************************************/
4973
4974 static NTSTATUS smb_set_file_size(connection_struct *conn,
4975                                   struct smb_request *req,
4976                                 files_struct *fsp,
4977                                 const char *fname,
4978                                 SMB_STRUCT_STAT *psbuf,
4979                                 SMB_OFF_T size)
4980 {
4981         NTSTATUS status = NT_STATUS_OK;
4982         files_struct *new_fsp = NULL;
4983
4984         if (!VALID_STAT(*psbuf)) {
4985                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4986         }
4987
4988         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4989
4990         if (size == get_file_size(*psbuf)) {
4991                 return NT_STATUS_OK;
4992         }
4993
4994         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4995                 fname, (double)size ));
4996
4997         if (fsp && fsp->fh->fd != -1) {
4998                 /* Handle based call. */
4999                 if (vfs_set_filelen(fsp, size) == -1) {
5000                         return map_nt_error_from_unix(errno);
5001                 }
5002                 trigger_write_time_update_immediate(fsp);
5003                 return NT_STATUS_OK;
5004         }
5005
5006         status = open_file_ntcreate(conn, req, fname, psbuf,
5007                                 FILE_WRITE_ATTRIBUTES,
5008                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5009                                 FILE_OPEN,
5010                                 0,
5011                                 FILE_ATTRIBUTE_NORMAL,
5012                                 FORCE_OPLOCK_BREAK_TO_NONE,
5013                                 NULL, &new_fsp);
5014         
5015         if (!NT_STATUS_IS_OK(status)) {
5016                 /* NB. We check for open_was_deferred in the caller. */
5017                 return status;
5018         }
5019
5020         if (vfs_set_filelen(new_fsp, size) == -1) {
5021                 status = map_nt_error_from_unix(errno);
5022                 close_file(req, new_fsp,NORMAL_CLOSE);
5023                 return status;
5024         }
5025
5026         trigger_write_time_update_immediate(new_fsp);
5027         close_file(req, new_fsp,NORMAL_CLOSE);
5028         return NT_STATUS_OK;
5029 }
5030
5031 /****************************************************************************
5032  Deal with SMB_INFO_SET_EA.
5033 ****************************************************************************/
5034
5035 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5036                                 const char *pdata,
5037                                 int total_data,
5038                                 files_struct *fsp,
5039                                 const char *fname)
5040 {
5041         struct ea_list *ea_list = NULL;
5042         TALLOC_CTX *ctx = NULL;
5043         NTSTATUS status = NT_STATUS_OK;
5044
5045         if (total_data < 10) {
5046
5047                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5048                    length. They seem to have no effect. Bug #3212. JRA */
5049
5050                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5051                         /* We're done. We only get EA info in this call. */
5052                         return NT_STATUS_OK;
5053                 }
5054
5055                 return NT_STATUS_INVALID_PARAMETER;
5056         }
5057
5058         if (IVAL(pdata,0) > total_data) {
5059                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5060                         IVAL(pdata,0), (unsigned int)total_data));
5061                 return NT_STATUS_INVALID_PARAMETER;
5062         }
5063
5064         ctx = talloc_tos();
5065         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5066         if (!ea_list) {
5067                 return NT_STATUS_INVALID_PARAMETER;
5068         }
5069         status = set_ea(conn, fsp, fname, ea_list);
5070
5071         return status;
5072 }
5073
5074 /****************************************************************************
5075  Deal with SMB_SET_FILE_DISPOSITION_INFO.
5076 ****************************************************************************/
5077
5078 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5079                                 const char *pdata,
5080                                 int total_data,
5081                                 files_struct *fsp,
5082                                 const char *fname,
5083                                 SMB_STRUCT_STAT *psbuf)
5084 {
5085         NTSTATUS status = NT_STATUS_OK;
5086         bool delete_on_close;
5087         uint32 dosmode = 0;
5088
5089         if (total_data < 1) {
5090                 return NT_STATUS_INVALID_PARAMETER;
5091         }
5092
5093         if (fsp == NULL) {
5094                 return NT_STATUS_INVALID_HANDLE;
5095         }
5096
5097         delete_on_close = (CVAL(pdata,0) ? True : False);
5098         dosmode = dos_mode(conn, fname, psbuf);
5099
5100         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5101                 "delete_on_close = %u\n",
5102                 fsp->fsp_name,
5103                 (unsigned int)dosmode,
5104                 (unsigned int)delete_on_close ));
5105
5106         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5107  
5108         if (!NT_STATUS_IS_OK(status)) {
5109                 return status;
5110         }
5111
5112         /* The set is across all open files on this dev/inode pair. */
5113         if (!set_delete_on_close(fsp, delete_on_close,
5114                                  &conn->server_info->utok)) {
5115                 return NT_STATUS_ACCESS_DENIED;
5116         }
5117         return NT_STATUS_OK;
5118 }
5119
5120 /****************************************************************************
5121  Deal with SMB_FILE_POSITION_INFORMATION.
5122 ****************************************************************************/
5123
5124 static NTSTATUS smb_file_position_information(connection_struct *conn,
5125                                 const char *pdata,
5126                                 int total_data,
5127                                 files_struct *fsp)
5128 {
5129         uint64_t position_information;
5130
5131         if (total_data < 8) {
5132                 return NT_STATUS_INVALID_PARAMETER;
5133         }
5134
5135         if (fsp == NULL) {
5136                 /* Ignore on pathname based set. */
5137                 return NT_STATUS_OK;
5138         }
5139
5140         position_information = (uint64_t)IVAL(pdata,0);
5141 #ifdef LARGE_SMB_OFF_T
5142         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5143 #else /* LARGE_SMB_OFF_T */
5144         if (IVAL(pdata,4) != 0) {
5145                 /* more than 32 bits? */
5146                 return NT_STATUS_INVALID_PARAMETER;
5147         }
5148 #endif /* LARGE_SMB_OFF_T */
5149
5150         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5151                 fsp->fsp_name, (double)position_information ));
5152         fsp->fh->position_information = position_information;
5153         return NT_STATUS_OK;
5154 }
5155
5156 /****************************************************************************
5157  Deal with SMB_FILE_MODE_INFORMATION.
5158 ****************************************************************************/
5159
5160 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5161                                 const char *pdata,
5162                                 int total_data)
5163 {
5164         uint32 mode;
5165
5166         if (total_data < 4) {
5167                 return NT_STATUS_INVALID_PARAMETER;
5168         }
5169         mode = IVAL(pdata,0);
5170         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5171                 return NT_STATUS_INVALID_PARAMETER;
5172         }
5173         return NT_STATUS_OK;
5174 }
5175
5176 /****************************************************************************
5177  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5178 ****************************************************************************/
5179
5180 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5181                                        struct smb_request *req,
5182                                        const char *pdata,
5183                                        int total_data,
5184                                        const char *fname)
5185 {
5186         char *link_target = NULL;
5187         const char *newname = fname;
5188         NTSTATUS status = NT_STATUS_OK;
5189         TALLOC_CTX *ctx = talloc_tos();
5190
5191         /* Set a symbolic link. */
5192         /* Don't allow this if follow links is false. */
5193
5194         if (total_data == 0) {
5195                 return NT_STATUS_INVALID_PARAMETER;
5196         }
5197
5198         if (!lp_symlinks(SNUM(conn))) {
5199                 return NT_STATUS_ACCESS_DENIED;
5200         }
5201
5202         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5203                     total_data, STR_TERMINATE);
5204
5205         if (!link_target) {
5206                 return NT_STATUS_INVALID_PARAMETER;
5207         }
5208
5209         /* !widelinks forces the target path to be within the share. */
5210         /* This means we can interpret the target as a pathname. */
5211         if (!lp_widelinks(SNUM(conn))) {
5212                 char *rel_name = NULL;
5213                 char *last_dirp = NULL;
5214
5215                 if (*link_target == '/') {
5216                         /* No absolute paths allowed. */
5217                         return NT_STATUS_ACCESS_DENIED;
5218                 }
5219                 rel_name = talloc_strdup(ctx,newname);
5220                 if (!rel_name) {
5221                         return NT_STATUS_NO_MEMORY;
5222                 }
5223                 last_dirp = strrchr_m(rel_name, '/');
5224                 if (last_dirp) {
5225                         last_dirp[1] = '\0';
5226                 } else {
5227                         rel_name = talloc_strdup(ctx,"./");
5228                         if (!rel_name) {
5229                                 return NT_STATUS_NO_MEMORY;
5230                         }
5231                 }
5232                 rel_name = talloc_asprintf_append(rel_name,
5233                                 "%s",
5234                                 link_target);
5235                 if (!rel_name) {
5236                         return NT_STATUS_NO_MEMORY;
5237                 }
5238
5239                 status = check_name(conn, rel_name);
5240                 if (!NT_STATUS_IS_OK(status)) {
5241                         return status;
5242                 }
5243         }
5244
5245         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5246                         newname, link_target ));
5247
5248         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5249                 return map_nt_error_from_unix(errno);
5250         }
5251
5252         return NT_STATUS_OK;
5253 }
5254
5255 /****************************************************************************
5256  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5257 ****************************************************************************/
5258
5259 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5260                                         struct smb_request *req,
5261                                         const char *pdata, int total_data,
5262                                         const char *fname)
5263 {
5264         char *oldname = NULL;
5265         TALLOC_CTX *ctx = talloc_tos();
5266         NTSTATUS status = NT_STATUS_OK;
5267
5268         /* Set a hard link. */
5269         if (total_data == 0) {
5270                 return NT_STATUS_INVALID_PARAMETER;
5271         }
5272
5273         srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5274                         total_data, STR_TERMINATE, &status);
5275         if (!NT_STATUS_IS_OK(status)) {
5276                 return status;
5277         }
5278
5279         status = resolve_dfspath(ctx, conn,
5280                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
5281                                 oldname,
5282                                 &oldname);
5283         if (!NT_STATUS_IS_OK(status)) {
5284                 return status;
5285         }
5286
5287         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5288                 fname, oldname));
5289
5290         return hardlink_internals(ctx, conn, oldname, fname);
5291 }
5292
5293 /****************************************************************************
5294  Deal with SMB_FILE_RENAME_INFORMATION.
5295 ****************************************************************************/
5296
5297 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5298                                             struct smb_request *req,
5299                                             const char *pdata,
5300                                             int total_data,
5301                                             files_struct *fsp,
5302                                             const char *fname)
5303 {
5304         bool overwrite;
5305         uint32 root_fid;
5306         uint32 len;
5307         char *newname = NULL;
5308         char *base_name = NULL;
5309         bool dest_has_wcard = False;
5310         NTSTATUS status = NT_STATUS_OK;
5311         char *p;
5312         TALLOC_CTX *ctx = talloc_tos();
5313
5314         if (total_data < 13) {
5315                 return NT_STATUS_INVALID_PARAMETER;
5316         }
5317
5318         overwrite = (CVAL(pdata,0) ? True : False);
5319         root_fid = IVAL(pdata,4);
5320         len = IVAL(pdata,8);
5321
5322         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5323                 return NT_STATUS_INVALID_PARAMETER;
5324         }
5325
5326         srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5327                               len, 0, &status,
5328                               &dest_has_wcard);
5329         if (!NT_STATUS_IS_OK(status)) {
5330                 return status;
5331         }
5332
5333         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5334                                 newname));
5335
5336         status = resolve_dfspath_wcard(ctx, conn,
5337                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5338                                        newname,
5339                                        &newname,
5340                                        &dest_has_wcard);
5341         if (!NT_STATUS_IS_OK(status)) {
5342                 return status;
5343         }
5344
5345         /* Check the new name has no '/' characters. */
5346         if (strchr_m(newname, '/')) {
5347                 return NT_STATUS_NOT_SUPPORTED;
5348         }
5349
5350         /* Create the base directory. */
5351         base_name = talloc_strdup(ctx, fname);
5352         if (!base_name) {
5353                 return NT_STATUS_NO_MEMORY;
5354         }
5355         p = strrchr_m(base_name, '/');
5356         if (p) {
5357                 p[1] = '\0';
5358         } else {
5359                 base_name = talloc_strdup(ctx, "./");
5360                 if (!base_name) {
5361                         return NT_STATUS_NO_MEMORY;
5362                 }
5363         }
5364         /* Append the new name. */
5365         base_name = talloc_asprintf_append(base_name,
5366                         "%s",
5367                         newname);
5368         if (!base_name) {
5369                 return NT_STATUS_NO_MEMORY;
5370         }
5371
5372         if (fsp) {
5373                 SMB_STRUCT_STAT sbuf;
5374                 char *newname_last_component = NULL;
5375
5376                 ZERO_STRUCT(sbuf);
5377
5378                 status = unix_convert(ctx, conn, newname, False,
5379                                         &newname,
5380                                         &newname_last_component,
5381                                         &sbuf);
5382
5383                 /* If an error we expect this to be
5384                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5385
5386                 if (!NT_STATUS_IS_OK(status)
5387                     && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5388                                         status)) {
5389                         return status;
5390                 }
5391
5392                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5393                         fsp->fnum, fsp->fsp_name, base_name ));
5394                 status = rename_internals_fsp(conn, fsp, base_name,
5395                                               newname_last_component, 0,
5396                                               overwrite);
5397         } else {
5398                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5399                         fname, base_name ));
5400                 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5401                                         overwrite, False, dest_has_wcard,
5402                                         FILE_WRITE_ATTRIBUTES);
5403         }
5404
5405         return status;
5406 }
5407
5408 /****************************************************************************
5409  Deal with SMB_SET_POSIX_ACL.
5410 ****************************************************************************/
5411
5412 #if defined(HAVE_POSIX_ACLS)
5413 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5414                                 const char *pdata,
5415                                 int total_data,
5416                                 files_struct *fsp,
5417                                 const char *fname,
5418                                 SMB_STRUCT_STAT *psbuf)
5419 {
5420         uint16 posix_acl_version;
5421         uint16 num_file_acls;
5422         uint16 num_def_acls;
5423         bool valid_file_acls = True;
5424         bool valid_def_acls = True;
5425
5426         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5427                 return NT_STATUS_INVALID_PARAMETER;
5428         }
5429         posix_acl_version = SVAL(pdata,0);
5430         num_file_acls = SVAL(pdata,2);
5431         num_def_acls = SVAL(pdata,4);
5432
5433         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5434                 valid_file_acls = False;
5435                 num_file_acls = 0;
5436         }
5437
5438         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5439                 valid_def_acls = False;
5440                 num_def_acls = 0;
5441         }
5442
5443         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5444                 return NT_STATUS_INVALID_PARAMETER;
5445         }
5446
5447         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5448                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5449                 return NT_STATUS_INVALID_PARAMETER;
5450         }
5451
5452         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5453                 fname ? fname : fsp->fsp_name,
5454                 (unsigned int)num_file_acls,
5455                 (unsigned int)num_def_acls));
5456
5457         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5458                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5459                 return map_nt_error_from_unix(errno);
5460         }
5461
5462         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5463                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
5464                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5465                 return map_nt_error_from_unix(errno);
5466         }
5467         return NT_STATUS_OK;
5468 }
5469 #endif
5470
5471 /****************************************************************************
5472  Deal with SMB_SET_POSIX_LOCK.
5473 ****************************************************************************/
5474
5475 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5476                                 struct smb_request *req,
5477                                 const char *pdata,
5478                                 int total_data,
5479                                 files_struct *fsp)
5480 {
5481         uint64_t count;
5482         uint64_t offset;
5483         uint32 lock_pid;
5484         bool blocking_lock = False;
5485         enum brl_type lock_type;
5486
5487         NTSTATUS status = NT_STATUS_OK;
5488
5489         if (fsp == NULL || fsp->fh->fd == -1) {
5490                 return NT_STATUS_INVALID_HANDLE;
5491         }
5492
5493         if (total_data != POSIX_LOCK_DATA_SIZE) {
5494                 return NT_STATUS_INVALID_PARAMETER;
5495         }
5496
5497         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5498                 case POSIX_LOCK_TYPE_READ:
5499                         lock_type = READ_LOCK;
5500                         break;
5501                 case POSIX_LOCK_TYPE_WRITE:
5502                         /* Return the right POSIX-mappable error code for files opened read-only. */
5503                         if (!fsp->can_write) {
5504                                 return NT_STATUS_INVALID_HANDLE;
5505                         }
5506                         lock_type = WRITE_LOCK;
5507                         break;
5508                 case POSIX_LOCK_TYPE_UNLOCK:
5509                         lock_type = UNLOCK_LOCK;
5510                         break;
5511                 default:
5512                         return NT_STATUS_INVALID_PARAMETER;
5513         }
5514
5515         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5516                 blocking_lock = False;
5517         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5518                 blocking_lock = True;
5519         } else {
5520                 return NT_STATUS_INVALID_PARAMETER;
5521         }
5522
5523         if (!lp_blocking_locks(SNUM(conn))) { 
5524                 blocking_lock = False;
5525         }
5526
5527         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5528 #if defined(HAVE_LONGLONG)
5529         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5530                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5531         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5532                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5533 #else /* HAVE_LONGLONG */
5534         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5535         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5536 #endif /* HAVE_LONGLONG */
5537
5538         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5539                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
5540                 fsp->fsp_name,
5541                 (unsigned int)lock_type,
5542                 (unsigned int)lock_pid,
5543                 (double)count,
5544                 (double)offset ));
5545
5546         if (lock_type == UNLOCK_LOCK) {
5547                 status = do_unlock(smbd_messaging_context(),
5548                                 fsp,
5549                                 lock_pid,
5550                                 count,
5551                                 offset,
5552                                 POSIX_LOCK);
5553         } else {
5554                 uint32 block_smbpid;
5555
5556                 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5557                                                         fsp,
5558                                                         lock_pid,
5559                                                         count,
5560                                                         offset,
5561                                                         lock_type,
5562                                                         POSIX_LOCK,
5563                                                         blocking_lock,
5564                                                         &status,
5565                                                         &block_smbpid);
5566
5567                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5568                         /*
5569                          * A blocking lock was requested. Package up
5570                          * this smb into a queued request and push it
5571                          * onto the blocking lock queue.
5572                          */
5573                         if(push_blocking_lock_request(br_lck,
5574                                                 req,
5575                                                 fsp,
5576                                                 -1, /* infinite timeout. */
5577                                                 0,
5578                                                 lock_pid,
5579                                                 lock_type,
5580                                                 POSIX_LOCK,
5581                                                 offset,
5582                                                 count,
5583                                                 block_smbpid)) {
5584                                 TALLOC_FREE(br_lck);
5585                                 return status;
5586                         }
5587                 }
5588                 TALLOC_FREE(br_lck);
5589         }
5590
5591         return status;
5592 }
5593
5594 /****************************************************************************
5595  Deal with SMB_INFO_STANDARD.
5596 ****************************************************************************/
5597
5598 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5599                                         const char *pdata,
5600                                         int total_data,
5601                                         files_struct *fsp,
5602                                         const char *fname,
5603                                         const SMB_STRUCT_STAT *psbuf)
5604 {
5605         struct timespec ts[2];
5606
5607         if (total_data < 12) {
5608                 return NT_STATUS_INVALID_PARAMETER;
5609         }
5610
5611         /* access time */
5612         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5613         /* write time */
5614         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5615
5616         DEBUG(10,("smb_set_info_standard: file %s\n",
5617                 fname ? fname : fsp->fsp_name ));
5618
5619         return smb_set_file_time(conn,
5620                                 fsp,
5621                                 fname,
5622                                 psbuf,
5623                                 ts,
5624                                 true);
5625 }
5626
5627 /****************************************************************************
5628  Deal with SMB_SET_FILE_BASIC_INFO.
5629 ****************************************************************************/
5630
5631 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5632                                         const char *pdata,
5633                                         int total_data,
5634                                         files_struct *fsp,
5635                                         const char *fname,
5636                                         SMB_STRUCT_STAT *psbuf)
5637 {
5638         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5639         struct timespec write_time;
5640         struct timespec changed_time;
5641         uint32 dosmode = 0;
5642         struct timespec ts[2];
5643         NTSTATUS status = NT_STATUS_OK;
5644         bool setting_write_time = true;
5645
5646         if (total_data < 36) {
5647                 return NT_STATUS_INVALID_PARAMETER;
5648         }
5649
5650         /* Set the attributes */
5651         dosmode = IVAL(pdata,32);
5652         status = smb_set_file_dosmode(conn,
5653                                         fname,
5654                                         psbuf,
5655                                         dosmode);
5656         if (!NT_STATUS_IS_OK(status)) {
5657                 return status;
5658         }
5659
5660         /* Ignore create time at offset pdata. */
5661
5662         /* access time */
5663         ts[0] = interpret_long_date(pdata+8);
5664
5665         write_time = interpret_long_date(pdata+16);
5666         changed_time = interpret_long_date(pdata+24);
5667
5668         /* mtime */
5669         ts[1] = timespec_min(&write_time, &changed_time);
5670
5671         if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5672                 ts[1] = write_time;
5673         }
5674
5675         /* Prefer a defined time to an undefined one. */
5676         if (null_timespec(ts[1])) {
5677                 if (null_timespec(write_time)) {
5678                         ts[1] = changed_time;
5679                         setting_write_time = false;
5680                 } else {
5681                         ts[1] = write_time;
5682                 }
5683         }
5684
5685         DEBUG(10,("smb_set_file_basic_info: file %s\n",
5686                 fname ? fname : fsp->fsp_name ));
5687
5688         return smb_set_file_time(conn,
5689                                 fsp,
5690                                 fname,
5691                                 psbuf,
5692                                 ts,
5693                                 setting_write_time);
5694 }
5695
5696 /****************************************************************************
5697  Deal with SMB_SET_FILE_ALLOCATION_INFO.
5698 ****************************************************************************/
5699
5700 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5701                                              struct smb_request *req,
5702                                         const char *pdata,
5703                                         int total_data,
5704                                         files_struct *fsp,
5705                                         const char *fname,
5706                                         SMB_STRUCT_STAT *psbuf)
5707 {
5708         uint64_t allocation_size = 0;
5709         NTSTATUS status = NT_STATUS_OK;
5710         files_struct *new_fsp = NULL;
5711
5712         if (!VALID_STAT(*psbuf)) {
5713                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5714         }
5715
5716         if (total_data < 8) {
5717                 return NT_STATUS_INVALID_PARAMETER;
5718         }
5719
5720         allocation_size = (uint64_t)IVAL(pdata,0);
5721 #ifdef LARGE_SMB_OFF_T
5722         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5723 #else /* LARGE_SMB_OFF_T */
5724         if (IVAL(pdata,4) != 0) {
5725                 /* more than 32 bits? */
5726                 return NT_STATUS_INVALID_PARAMETER;
5727         }
5728 #endif /* LARGE_SMB_OFF_T */
5729
5730         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5731                         fname, (double)allocation_size ));
5732
5733         if (allocation_size) {
5734                 allocation_size = smb_roundup(conn, allocation_size);
5735         }
5736
5737         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5738                         fname, (double)allocation_size ));
5739
5740         if (fsp && fsp->fh->fd != -1) {
5741                 /* Open file handle. */
5742                 /* Only change if needed. */
5743                 if (allocation_size != get_file_size(*psbuf)) {
5744                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5745                                 return map_nt_error_from_unix(errno);
5746                         }
5747                 }
5748                 /* But always update the time. */
5749                 /*
5750                  * This is equivalent to a write. Ensure it's seen immediately
5751                  * if there are no pending writes.
5752                  */
5753                 trigger_write_time_update_immediate(fsp);
5754                 return NT_STATUS_OK;
5755         }
5756
5757         /* Pathname or stat or directory file. */
5758
5759         status = open_file_ntcreate(conn, req, fname, psbuf,
5760                                 FILE_WRITE_DATA,
5761                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5762                                 FILE_OPEN,
5763                                 0,
5764                                 FILE_ATTRIBUTE_NORMAL,
5765                                 FORCE_OPLOCK_BREAK_TO_NONE,
5766                                 NULL, &new_fsp);
5767
5768         if (!NT_STATUS_IS_OK(status)) {
5769                 /* NB. We check for open_was_deferred in the caller. */
5770                 return status;
5771         }
5772
5773         /* Only change if needed. */
5774         if (allocation_size != get_file_size(*psbuf)) {
5775                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5776                         status = map_nt_error_from_unix(errno);
5777                         close_file(req, new_fsp, NORMAL_CLOSE);
5778                         return status;
5779                 }
5780         }
5781
5782         /* Changing the allocation size should set the last mod time. */
5783         /*
5784          * This is equivalent to a write. Ensure it's seen immediately
5785          * if there are no pending writes.
5786          */
5787         trigger_write_time_update_immediate(new_fsp);
5788
5789         close_file(req, new_fsp, NORMAL_CLOSE);
5790         return NT_STATUS_OK;
5791 }
5792
5793 /****************************************************************************
5794  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5795 ****************************************************************************/
5796
5797 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5798                                               struct smb_request *req,
5799                                         const char *pdata,
5800                                         int total_data,
5801                                         files_struct *fsp,
5802                                         const char *fname,
5803                                         SMB_STRUCT_STAT *psbuf)
5804 {
5805         SMB_OFF_T size;
5806
5807         if (total_data < 8) {
5808                 return NT_STATUS_INVALID_PARAMETER;
5809         }
5810
5811         size = IVAL(pdata,0);
5812 #ifdef LARGE_SMB_OFF_T
5813         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5814 #else /* LARGE_SMB_OFF_T */
5815         if (IVAL(pdata,4) != 0) {
5816                 /* more than 32 bits? */
5817                 return NT_STATUS_INVALID_PARAMETER;
5818         }
5819 #endif /* LARGE_SMB_OFF_T */
5820         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5821                 "file %s to %.0f\n", fname, (double)size ));
5822
5823         return smb_set_file_size(conn, req,
5824                                 fsp,
5825                                 fname,
5826                                 psbuf,
5827                                 size);
5828 }
5829
5830 /****************************************************************************
5831  Allow a UNIX info mknod.
5832 ****************************************************************************/
5833
5834 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5835                                         const char *pdata,
5836                                         int total_data,
5837                                         const char *fname,
5838                                         SMB_STRUCT_STAT *psbuf)
5839 {
5840         uint32 file_type = IVAL(pdata,56);
5841 #if defined(HAVE_MAKEDEV)
5842         uint32 dev_major = IVAL(pdata,60);
5843         uint32 dev_minor = IVAL(pdata,68);
5844 #endif
5845         SMB_DEV_T dev = (SMB_DEV_T)0;
5846         uint32 raw_unixmode = IVAL(pdata,84);
5847         NTSTATUS status;
5848         mode_t unixmode;
5849
5850         if (total_data < 100) {
5851                 return NT_STATUS_INVALID_PARAMETER;
5852         }
5853
5854         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5855         if (!NT_STATUS_IS_OK(status)) {
5856                 return status;
5857         }
5858
5859 #if defined(HAVE_MAKEDEV)
5860         dev = makedev(dev_major, dev_minor);
5861 #endif
5862
5863         switch (file_type) {
5864 #if defined(S_IFIFO)
5865                 case UNIX_TYPE_FIFO:
5866                         unixmode |= S_IFIFO;
5867                         break;
5868 #endif
5869 #if defined(S_IFSOCK)
5870                 case UNIX_TYPE_SOCKET:
5871                         unixmode |= S_IFSOCK;
5872                         break;
5873 #endif
5874 #if defined(S_IFCHR)
5875                 case UNIX_TYPE_CHARDEV:
5876                         unixmode |= S_IFCHR;
5877                         break;
5878 #endif
5879 #if defined(S_IFBLK)
5880                 case UNIX_TYPE_BLKDEV:
5881                         unixmode |= S_IFBLK;
5882                         break;
5883 #endif
5884                 default:
5885                         return NT_STATUS_INVALID_PARAMETER;
5886         }
5887
5888         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5889 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5890
5891         /* Ok - do the mknod. */
5892         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5893                 return map_nt_error_from_unix(errno);
5894         }
5895
5896         /* If any of the other "set" calls fail we
5897          * don't want to end up with a half-constructed mknod.
5898          */
5899
5900         if (lp_inherit_perms(SNUM(conn))) {
5901                 inherit_access_posix_acl(
5902                         conn, parent_dirname(fname),
5903                         fname, unixmode);
5904         }
5905
5906         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5907                 status = map_nt_error_from_unix(errno);
5908                 SMB_VFS_UNLINK(conn,fname);
5909                 return status;
5910         }
5911         return NT_STATUS_OK;
5912 }
5913
5914 /****************************************************************************
5915  Deal with SMB_SET_FILE_UNIX_BASIC.
5916 ****************************************************************************/
5917
5918 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5919                                         struct smb_request *req,
5920                                         const char *pdata,
5921                                         int total_data,
5922                                         files_struct *fsp,
5923                                         const char *fname,
5924                                         SMB_STRUCT_STAT *psbuf)
5925 {
5926         struct timespec ts[2];
5927         uint32 raw_unixmode;
5928         mode_t unixmode;
5929         SMB_OFF_T size = 0;
5930         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5931         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5932         NTSTATUS status = NT_STATUS_OK;
5933         bool delete_on_fail = False;
5934         enum perm_type ptype;
5935
5936         if (total_data < 100) {
5937                 return NT_STATUS_INVALID_PARAMETER;
5938         }
5939
5940         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5941            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5942                 size=IVAL(pdata,0); /* first 8 Bytes are size */
5943 #ifdef LARGE_SMB_OFF_T
5944                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5945 #else /* LARGE_SMB_OFF_T */
5946                 if (IVAL(pdata,4) != 0) {
5947                         /* more than 32 bits? */
5948                         return NT_STATUS_INVALID_PARAMETER;
5949                 }
5950 #endif /* LARGE_SMB_OFF_T */
5951         }
5952
5953         ts[0] = interpret_long_date(pdata+24); /* access_time */
5954         ts[1] = interpret_long_date(pdata+32); /* modification_time */
5955         set_owner = (uid_t)IVAL(pdata,40);
5956         set_grp = (gid_t)IVAL(pdata,48);
5957         raw_unixmode = IVAL(pdata,84);
5958
5959         if (VALID_STAT(*psbuf)) {
5960                 if (S_ISDIR(psbuf->st_mode)) {
5961                         ptype = PERM_EXISTING_DIR;
5962                 } else {
5963                         ptype = PERM_EXISTING_FILE;
5964                 }
5965         } else {
5966                 ptype = PERM_NEW_FILE;
5967         }
5968
5969         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5970         if (!NT_STATUS_IS_OK(status)) {
5971                 return status;
5972         }
5973
5974         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5975 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5976                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5977
5978         if (!VALID_STAT(*psbuf)) {
5979                 /*
5980                  * The only valid use of this is to create character and block
5981                  * devices, and named pipes. This is deprecated (IMHO) and 
5982                  * a new info level should be used for mknod. JRA.
5983                  */
5984
5985                 status = smb_unix_mknod(conn,
5986                                         pdata,
5987                                         total_data,
5988                                         fname,
5989                                         psbuf);
5990                 if (!NT_STATUS_IS_OK(status)) {
5991                         return status;
5992                 }
5993
5994                 /* Ensure we don't try and change anything else. */
5995                 raw_unixmode = SMB_MODE_NO_CHANGE;
5996                 size = get_file_size(*psbuf);
5997                 ts[0] = get_atimespec(psbuf);
5998                 ts[1] = get_mtimespec(psbuf);
5999                 /* 
6000                  * We continue here as we might want to change the 
6001                  * owner uid/gid.
6002                  */
6003                 delete_on_fail = True;
6004         }
6005
6006 #if 1
6007         /* Horrible backwards compatibility hack as an old server bug
6008          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6009          * */
6010
6011         if (!size) {
6012                 size = get_file_size(*psbuf);
6013         }
6014 #endif
6015
6016         /*
6017          * Deal with the UNIX specific mode set.
6018          */
6019
6020         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6021                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6022                         (unsigned int)unixmode, fname ));
6023                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6024                         return map_nt_error_from_unix(errno);
6025                 }
6026         }
6027
6028         /*
6029          * Deal with the UNIX specific uid set.
6030          */
6031
6032         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6033                 int ret;
6034
6035                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6036                         (unsigned int)set_owner, fname ));
6037
6038                 if (S_ISLNK(psbuf->st_mode)) {
6039                         ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6040                 } else {
6041                         ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6042                 }
6043
6044                 if (ret != 0) {
6045                         status = map_nt_error_from_unix(errno);
6046                         if (delete_on_fail) {
6047                                 SMB_VFS_UNLINK(conn,fname);
6048                         }
6049                         return status;
6050                 }
6051         }
6052
6053         /*
6054          * Deal with the UNIX specific gid set.
6055          */
6056
6057         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6058                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6059                         (unsigned int)set_owner, fname ));
6060                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6061                         status = map_nt_error_from_unix(errno);
6062                         if (delete_on_fail) {
6063                                 SMB_VFS_UNLINK(conn,fname);
6064                         }
6065                         return status;
6066                 }
6067         }
6068
6069         /* Deal with any size changes. */
6070
6071         status = smb_set_file_size(conn, req,
6072                                 fsp,
6073                                 fname,
6074                                 psbuf,
6075                                 size);
6076         if (!NT_STATUS_IS_OK(status)) {
6077                 return status;
6078         }
6079
6080         /* Deal with any time changes. */
6081
6082         return smb_set_file_time(conn,
6083                                 fsp,
6084                                 fname,
6085                                 psbuf,
6086                                 ts,
6087                                 true);
6088 }
6089
6090 /****************************************************************************
6091  Deal with SMB_SET_FILE_UNIX_INFO2.
6092 ****************************************************************************/
6093
6094 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6095                                         struct smb_request *req,
6096                                         const char *pdata,
6097                                         int total_data,
6098                                         files_struct *fsp,
6099                                         const char *fname,
6100                                         SMB_STRUCT_STAT *psbuf)
6101 {
6102         NTSTATUS status;
6103         uint32 smb_fflags;
6104         uint32 smb_fmask;
6105
6106         if (total_data < 116) {
6107                 return NT_STATUS_INVALID_PARAMETER;
6108         }
6109
6110         /* Start by setting all the fields that are common between UNIX_BASIC
6111          * and UNIX_INFO2.
6112          */
6113         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6114                                 fsp, fname, psbuf);
6115         if (!NT_STATUS_IS_OK(status)) {
6116                 return status;
6117         }
6118
6119         smb_fflags = IVAL(pdata, 108);
6120         smb_fmask = IVAL(pdata, 112);
6121
6122         /* NB: We should only attempt to alter the file flags if the client
6123          * sends a non-zero mask.
6124          */
6125         if (smb_fmask != 0) {
6126                 int stat_fflags = 0;
6127
6128                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6129                             &stat_fflags)) {
6130                         /* Client asked to alter a flag we don't understand. */
6131                         return NT_STATUS_INVALID_PARAMETER;
6132                 }
6133
6134                 if (fsp && fsp->fh->fd != -1) {
6135                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
6136                         return NT_STATUS_NOT_SUPPORTED;
6137                 } else {
6138                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6139                                 return map_nt_error_from_unix(errno);
6140                         }
6141                 }
6142         }
6143
6144         /* XXX: need to add support for changing the create_time here. You
6145          * can do this for paths on Darwin with setattrlist(2). The right way
6146          * to hook this up is probably by extending the VFS utimes interface.
6147          */
6148
6149         return NT_STATUS_OK;
6150 }
6151
6152 /****************************************************************************
6153  Create a directory with POSIX semantics.
6154 ****************************************************************************/
6155
6156 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6157                                 struct smb_request *req,
6158                                 char **ppdata,
6159                                 int total_data,
6160                                 const char *fname,
6161                                 SMB_STRUCT_STAT *psbuf,
6162                                 int *pdata_return_size)
6163 {
6164         NTSTATUS status = NT_STATUS_OK;
6165         uint32 raw_unixmode = 0;
6166         uint32 mod_unixmode = 0;
6167         mode_t unixmode = (mode_t)0;
6168         files_struct *fsp = NULL;
6169         uint16 info_level_return = 0;
6170         int info;
6171         char *pdata = *ppdata;
6172
6173         if (total_data < 18) {
6174                 return NT_STATUS_INVALID_PARAMETER;
6175         }
6176
6177         raw_unixmode = IVAL(pdata,8);
6178         /* Next 4 bytes are not yet defined. */
6179
6180         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6181         if (!NT_STATUS_IS_OK(status)) {
6182                 return status;
6183         }
6184
6185         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6186
6187         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6188                 fname, (unsigned int)unixmode ));
6189
6190         status = open_directory(conn, req,
6191                                 fname,
6192                                 psbuf,
6193                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
6194                                 FILE_SHARE_NONE, /* Ignored for stat opens */
6195                                 FILE_CREATE,
6196                                 0,
6197                                 mod_unixmode,
6198                                 &info,
6199                                 &fsp);
6200
6201         if (NT_STATUS_IS_OK(status)) {
6202                 close_file(req, fsp, NORMAL_CLOSE);
6203         }
6204
6205         info_level_return = SVAL(pdata,16);
6206  
6207         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6208                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6209         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6210                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6211         } else {
6212                 *pdata_return_size = 12;
6213         }
6214
6215         /* Realloc the data size */
6216         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6217         if (*ppdata == NULL) {
6218                 *pdata_return_size = 0;
6219                 return NT_STATUS_NO_MEMORY;
6220         }
6221         pdata = *ppdata;
6222
6223         SSVAL(pdata,0,NO_OPLOCK_RETURN);
6224         SSVAL(pdata,2,0); /* No fnum. */
6225         SIVAL(pdata,4,info); /* Was directory created. */
6226
6227         switch (info_level_return) {
6228                 case SMB_QUERY_FILE_UNIX_BASIC:
6229                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6230                         SSVAL(pdata,10,0); /* Padding. */
6231                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6232                         break;
6233                 case SMB_QUERY_FILE_UNIX_INFO2:
6234                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6235                         SSVAL(pdata,10,0); /* Padding. */
6236                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6237                         break;
6238                 default:
6239                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6240                         SSVAL(pdata,10,0); /* Padding. */
6241                         break;
6242         }
6243
6244         return status;
6245 }
6246
6247 /****************************************************************************
6248  Open/Create a file with POSIX semantics.
6249 ****************************************************************************/
6250
6251 static NTSTATUS smb_posix_open(connection_struct *conn,
6252                                struct smb_request *req,
6253                                 char **ppdata,
6254                                 int total_data,
6255                                 const char *fname,
6256                                 SMB_STRUCT_STAT *psbuf,
6257                                 int *pdata_return_size)
6258 {
6259         bool extended_oplock_granted = False;
6260         char *pdata = *ppdata;
6261         uint32 flags = 0;
6262         uint32 wire_open_mode = 0;
6263         uint32 raw_unixmode = 0;
6264         uint32 mod_unixmode = 0;
6265         uint32 create_disp = 0;
6266         uint32 access_mask = 0;
6267         uint32 create_options = 0;
6268         NTSTATUS status = NT_STATUS_OK;
6269         mode_t unixmode = (mode_t)0;
6270         files_struct *fsp = NULL;
6271         int oplock_request = 0;
6272         int info = 0;
6273         uint16 info_level_return = 0;
6274
6275         if (total_data < 18) {
6276                 return NT_STATUS_INVALID_PARAMETER;
6277         }
6278
6279         flags = IVAL(pdata,0);
6280         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6281         if (oplock_request) {
6282                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6283         }
6284
6285         wire_open_mode = IVAL(pdata,4);
6286
6287         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6288                 return smb_posix_mkdir(conn, req,
6289                                         ppdata,
6290                                         total_data,
6291                                         fname,
6292                                         psbuf,
6293                                         pdata_return_size);
6294         }
6295
6296         switch (wire_open_mode & SMB_ACCMODE) {
6297                 case SMB_O_RDONLY:
6298                         access_mask = FILE_READ_DATA;
6299                         break;
6300                 case SMB_O_WRONLY:
6301                         access_mask = FILE_WRITE_DATA;
6302                         break;
6303                 case SMB_O_RDWR:
6304                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6305                         break;
6306                 default:
6307                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6308                                 (unsigned int)wire_open_mode ));
6309                         return NT_STATUS_INVALID_PARAMETER;
6310         }
6311
6312         wire_open_mode &= ~SMB_ACCMODE;
6313
6314         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6315                 create_disp = FILE_CREATE;
6316         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6317                 create_disp = FILE_OVERWRITE_IF;
6318         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6319                 create_disp = FILE_OPEN_IF;
6320         } else {
6321                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6322                         (unsigned int)wire_open_mode ));
6323                 return NT_STATUS_INVALID_PARAMETER;
6324         }
6325
6326         raw_unixmode = IVAL(pdata,8);
6327         /* Next 4 bytes are not yet defined. */
6328
6329         status = unix_perms_from_wire(conn,
6330                                 psbuf,
6331                                 raw_unixmode,
6332                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6333                                 &unixmode);
6334
6335         if (!NT_STATUS_IS_OK(status)) {
6336                 return status;
6337         }
6338
6339         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6340
6341         if (wire_open_mode & SMB_O_SYNC) {
6342                 create_options |= FILE_WRITE_THROUGH;
6343         }
6344         if (wire_open_mode & SMB_O_APPEND) {
6345                 access_mask |= FILE_APPEND_DATA;
6346         }
6347         if (wire_open_mode & SMB_O_DIRECT) {
6348                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6349         }
6350
6351         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6352                 fname,
6353                 (unsigned int)wire_open_mode,
6354                 (unsigned int)unixmode ));
6355
6356         status = open_file_ntcreate(conn, req,
6357                                 fname,
6358                                 psbuf,
6359                                 access_mask,
6360                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6361                                 create_disp,
6362                                 0,              /* no create options yet. */
6363                                 mod_unixmode,
6364                                 oplock_request,
6365                                 &info,
6366                                 &fsp);
6367
6368         if (!NT_STATUS_IS_OK(status)) {
6369                 return status;
6370         }
6371
6372         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6373                 extended_oplock_granted = True;
6374         }
6375
6376         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6377                 extended_oplock_granted = True;
6378         }
6379
6380         info_level_return = SVAL(pdata,16);
6381  
6382         /* Allocate the correct return size. */
6383
6384         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6385                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6386         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6387                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6388         } else {
6389                 *pdata_return_size = 12;
6390         }
6391
6392         /* Realloc the data size */
6393         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6394         if (*ppdata == NULL) {
6395                 close_file(req, fsp, ERROR_CLOSE);
6396                 *pdata_return_size = 0;
6397                 return NT_STATUS_NO_MEMORY;
6398         }
6399         pdata = *ppdata;
6400
6401         if (extended_oplock_granted) {
6402                 if (flags & REQUEST_BATCH_OPLOCK) {
6403                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6404                 } else {
6405                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6406                 }
6407         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6408                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6409         } else {
6410                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6411         }
6412
6413         SSVAL(pdata,2,fsp->fnum);
6414         SIVAL(pdata,4,info); /* Was file created etc. */
6415
6416         switch (info_level_return) {
6417                 case SMB_QUERY_FILE_UNIX_BASIC:
6418                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6419                         SSVAL(pdata,10,0); /* padding. */
6420                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6421                         break;
6422                 case SMB_QUERY_FILE_UNIX_INFO2:
6423                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6424                         SSVAL(pdata,10,0); /* padding. */
6425                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6426                         break;
6427                 default:
6428                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6429                         SSVAL(pdata,10,0); /* padding. */
6430                         break;
6431         }
6432         return NT_STATUS_OK;
6433 }
6434
6435 /****************************************************************************
6436  Delete a file with POSIX semantics.
6437 ****************************************************************************/
6438
6439 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6440                                  struct smb_request *req,
6441                                 const char *pdata,
6442                                 int total_data,
6443                                 const char *fname,
6444                                 SMB_STRUCT_STAT *psbuf)
6445 {
6446         NTSTATUS status = NT_STATUS_OK;
6447         files_struct *fsp = NULL;
6448         uint16 flags = 0;
6449         char del = 1;
6450         int info = 0;
6451         int i;
6452         struct share_mode_lock *lck = NULL;
6453
6454         if (total_data < 2) {
6455                 return NT_STATUS_INVALID_PARAMETER;
6456         }
6457
6458         flags = SVAL(pdata,0);
6459
6460         if (!VALID_STAT(*psbuf)) {
6461                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6462         }
6463
6464         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6465                         !VALID_STAT_OF_DIR(*psbuf)) {
6466                 return NT_STATUS_NOT_A_DIRECTORY;
6467         }
6468
6469         DEBUG(10,("smb_posix_unlink: %s %s\n",
6470                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6471                 fname));
6472
6473         if (VALID_STAT_OF_DIR(*psbuf)) {
6474                 status = open_directory(conn, req,
6475                                         fname,
6476                                         psbuf,
6477                                         DELETE_ACCESS,
6478                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6479                                         FILE_OPEN,
6480                                         0,
6481                                         FILE_FLAG_POSIX_SEMANTICS|0777,
6482                                         &info,
6483                                         &fsp);
6484         } else {
6485
6486                 status = open_file_ntcreate(conn, req,
6487                                 fname,
6488                                 psbuf,
6489                                 DELETE_ACCESS,
6490                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6491                                 FILE_OPEN,
6492                                 0,
6493                                 FILE_FLAG_POSIX_SEMANTICS|0777,
6494                                 0, /* No oplock, but break existing ones. */
6495                                 &info,
6496                                 &fsp);
6497         }
6498
6499         if (!NT_STATUS_IS_OK(status)) {
6500                 return status;
6501         }
6502
6503         /*
6504          * Don't lie to client. If we can't really delete due to
6505          * non-POSIX opens return SHARING_VIOLATION.
6506          */
6507
6508         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6509                                   NULL);
6510         if (lck == NULL) {
6511                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6512                         "lock for file %s\n", fsp->fsp_name));
6513                 close_file(req, fsp, NORMAL_CLOSE);
6514                 return NT_STATUS_INVALID_PARAMETER;
6515         }
6516
6517         /*
6518          * See if others still have the file open. If this is the case, then
6519          * don't delete. If all opens are POSIX delete we can set the delete
6520          * on close disposition.
6521          */
6522         for (i=0; i<lck->num_share_modes; i++) {
6523                 struct share_mode_entry *e = &lck->share_modes[i];
6524                 if (is_valid_share_mode_entry(e)) {
6525                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6526                                 continue;
6527                         }
6528                         /* Fail with sharing violation. */
6529                         close_file(req, fsp, NORMAL_CLOSE);
6530                         TALLOC_FREE(lck);
6531                         return NT_STATUS_SHARING_VIOLATION;
6532                 }
6533         }
6534
6535         /*
6536          * Set the delete on close.
6537          */
6538         status = smb_set_file_disposition_info(conn,
6539                                                 &del,
6540                                                 1,
6541                                                 fsp,
6542                                                 fname,
6543                                                 psbuf);
6544
6545         if (!NT_STATUS_IS_OK(status)) {
6546                 close_file(req, fsp, NORMAL_CLOSE);
6547                 TALLOC_FREE(lck);
6548                 return status;
6549         }
6550         TALLOC_FREE(lck);
6551         return close_file(req, fsp, NORMAL_CLOSE);
6552 }
6553
6554 /****************************************************************************
6555  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6556 ****************************************************************************/
6557
6558 static void call_trans2setfilepathinfo(connection_struct *conn,
6559                                        struct smb_request *req,
6560                                        unsigned int tran_call,
6561                                        char **pparams, int total_params,
6562                                        char **ppdata, int total_data,
6563                                        unsigned int max_data_bytes)
6564 {
6565         char *params = *pparams;
6566         char *pdata = *ppdata;
6567         uint16 info_level;
6568         SMB_STRUCT_STAT sbuf;
6569         char *fname = NULL;
6570         files_struct *fsp = NULL;
6571         NTSTATUS status = NT_STATUS_OK;
6572         int data_return_size = 0;
6573         TALLOC_CTX *ctx = talloc_tos();
6574
6575         if (!params) {
6576                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6577                 return;
6578         }
6579
6580         ZERO_STRUCT(sbuf);
6581
6582         if (tran_call == TRANSACT2_SETFILEINFO) {
6583                 if (total_params < 4) {
6584                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6585                         return;
6586                 }
6587
6588                 fsp = file_fsp(req, SVAL(params,0));
6589                 /* Basic check for non-null fsp. */
6590                 if (!check_fsp_open(conn, req, fsp)) {
6591                         return;
6592                 }
6593                 info_level = SVAL(params,2);
6594
6595                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6596                 if (!fname) {
6597                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6598                         return;
6599                 }
6600
6601                 if(fsp->is_directory || fsp->fh->fd == -1) {
6602                         /*
6603                          * This is actually a SETFILEINFO on a directory
6604                          * handle (returned from an NT SMB). NT5.0 seems
6605                          * to do this call. JRA.
6606                          */
6607                         if (INFO_LEVEL_IS_UNIX(info_level)) {
6608                                 /* Always do lstat for UNIX calls. */
6609                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6610                                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6611                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6612                                         return;
6613                                 }
6614                         } else {
6615                                 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6616                                         DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6617                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6618                                         return;
6619                                 }
6620                         }
6621                 } else if (fsp->print_file) {
6622                         /*
6623                          * Doing a DELETE_ON_CLOSE should cancel a print job.
6624                          */
6625                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6626                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6627
6628                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6629
6630                                 SSVAL(params,0,0);
6631                                 send_trans2_replies(conn, req, params, 2,
6632                                                     *ppdata, 0,
6633                                                     max_data_bytes);
6634                                 return;
6635                         } else {
6636                                 reply_unixerror(req, ERRDOS, ERRbadpath);
6637                                 return;
6638                         }
6639                 } else {
6640                         /*
6641                          * Original code - this is an open file.
6642                          */
6643                         if (!check_fsp(conn, req, fsp)) {
6644                                 return;
6645                         }
6646
6647                         if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6648                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6649                                 reply_unixerror(req, ERRDOS, ERRbadfid);
6650                                 return;
6651                         }
6652                 }
6653         } else {
6654                 /* set path info */
6655                 if (total_params < 7) {
6656                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6657                         return;
6658                 }
6659
6660                 info_level = SVAL(params,0);
6661                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6662                                 total_params - 6, STR_TERMINATE,
6663                                 &status);
6664                 if (!NT_STATUS_IS_OK(status)) {
6665                         reply_nterror(req, status);
6666                         return;
6667                 }
6668
6669                 status = resolve_dfspath(ctx, conn,
6670                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
6671                                          fname,
6672                                          &fname);
6673                 if (!NT_STATUS_IS_OK(status)) {
6674                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6675                                 reply_botherror(req,
6676                                                 NT_STATUS_PATH_NOT_COVERED,
6677                                                 ERRSRV, ERRbadpath);
6678                                 return;
6679                         }
6680                         reply_nterror(req, status);
6681                         return;
6682                 }
6683
6684                 status = unix_convert(ctx, conn, fname, False,
6685                                 &fname, NULL, &sbuf);
6686                 if (!NT_STATUS_IS_OK(status)) {
6687                         reply_nterror(req, status);
6688                         return;
6689                 }
6690
6691                 status = check_name(conn, fname);
6692                 if (!NT_STATUS_IS_OK(status)) {
6693                         reply_nterror(req, status);
6694                         return;
6695                 }
6696
6697                 if (INFO_LEVEL_IS_UNIX(info_level)) {
6698                         /*
6699                          * For CIFS UNIX extensions the target name may not exist.
6700                          */
6701
6702                         /* Always do lstat for UNIX calls. */
6703                         SMB_VFS_LSTAT(conn,fname,&sbuf);
6704
6705                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6706                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6707                         reply_unixerror(req, ERRDOS, ERRbadpath);
6708                         return;
6709                 }
6710         }
6711
6712         if (!CAN_WRITE(conn)) {
6713                 reply_doserror(req, ERRSRV, ERRaccess);
6714                 return;
6715         }
6716
6717         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6718                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6719                 return;
6720         }
6721
6722         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6723                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6724
6725         /* Realloc the parameter size */
6726         *pparams = (char *)SMB_REALLOC(*pparams,2);
6727         if (*pparams == NULL) {
6728                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6729                 return;
6730         }
6731         params = *pparams;
6732
6733         SSVAL(params,0,0);
6734
6735         switch (info_level) {
6736
6737                 case SMB_INFO_STANDARD:
6738                 {
6739                         status = smb_set_info_standard(conn,
6740                                         pdata,
6741                                         total_data,
6742                                         fsp,
6743                                         fname,
6744                                         &sbuf);
6745                         break;
6746                 }
6747
6748                 case SMB_INFO_SET_EA:
6749                 {
6750                         status = smb_info_set_ea(conn,
6751                                                 pdata,
6752                                                 total_data,
6753                                                 fsp,
6754                                                 fname);
6755                         break;
6756                 }
6757
6758                 case SMB_SET_FILE_BASIC_INFO:
6759                 case SMB_FILE_BASIC_INFORMATION:
6760                 {
6761                         status = smb_set_file_basic_info(conn,
6762                                                         pdata,
6763                                                         total_data,
6764                                                         fsp,
6765                                                         fname,
6766                                                         &sbuf);
6767                         break;
6768                 }
6769
6770                 case SMB_FILE_ALLOCATION_INFORMATION:
6771                 case SMB_SET_FILE_ALLOCATION_INFO:
6772                 {
6773                         status = smb_set_file_allocation_info(conn, req,
6774                                                                 pdata,
6775                                                                 total_data,
6776                                                                 fsp,
6777                                                                 fname,
6778                                                                 &sbuf);
6779                         break;
6780                 }
6781
6782                 case SMB_FILE_END_OF_FILE_INFORMATION:
6783                 case SMB_SET_FILE_END_OF_FILE_INFO:
6784                 {
6785                         status = smb_set_file_end_of_file_info(conn, req,
6786                                                                 pdata,
6787                                                                 total_data,
6788                                                                 fsp,
6789                                                                 fname,
6790                                                                 &sbuf);
6791                         break;
6792                 }
6793
6794                 case SMB_FILE_DISPOSITION_INFORMATION:
6795                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6796                 {
6797 #if 0
6798                         /* JRA - We used to just ignore this on a path ? 
6799                          * Shouldn't this be invalid level on a pathname
6800                          * based call ?
6801                          */
6802                         if (tran_call != TRANSACT2_SETFILEINFO) {
6803                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6804                         }
6805 #endif
6806                         status = smb_set_file_disposition_info(conn,
6807                                                 pdata,
6808                                                 total_data,
6809                                                 fsp,
6810                                                 fname,
6811                                                 &sbuf);
6812                         break;
6813                 }
6814
6815                 case SMB_FILE_POSITION_INFORMATION:
6816                 {
6817                         status = smb_file_position_information(conn,
6818                                                 pdata,
6819                                                 total_data,
6820                                                 fsp);
6821                         break;
6822                 }
6823
6824                 /* From tridge Samba4 : 
6825                  * MODE_INFORMATION in setfileinfo (I have no
6826                  * idea what "mode information" on a file is - it takes a value of 0,
6827                  * 2, 4 or 6. What could it be?).
6828                  */
6829
6830                 case SMB_FILE_MODE_INFORMATION:
6831                 {
6832                         status = smb_file_mode_information(conn,
6833                                                 pdata,
6834                                                 total_data);
6835                         break;
6836                 }
6837
6838                 /*
6839                  * CIFS UNIX extensions.
6840                  */
6841
6842                 case SMB_SET_FILE_UNIX_BASIC:
6843                 {
6844                         status = smb_set_file_unix_basic(conn, req,
6845                                                         pdata,
6846                                                         total_data,
6847                                                         fsp,
6848                                                         fname,
6849                                                         &sbuf);
6850                         break;
6851                 }
6852
6853                 case SMB_SET_FILE_UNIX_INFO2:
6854                 {
6855                         status = smb_set_file_unix_info2(conn, req,
6856                                                         pdata,
6857                                                         total_data,
6858                                                         fsp,
6859                                                         fname,
6860                                                         &sbuf);
6861                         break;
6862                 }
6863
6864                 case SMB_SET_FILE_UNIX_LINK:
6865                 {
6866                         if (tran_call != TRANSACT2_SETPATHINFO) {
6867                                 /* We must have a pathname for this. */
6868                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6869                                 return;
6870                         }
6871                         status = smb_set_file_unix_link(conn, req, pdata,
6872                                                         total_data, fname);
6873                         break;
6874                 }
6875
6876                 case SMB_SET_FILE_UNIX_HLINK:
6877                 {
6878                         if (tran_call != TRANSACT2_SETPATHINFO) {
6879                                 /* We must have a pathname for this. */
6880                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6881                                 return;
6882                         }
6883                         status = smb_set_file_unix_hlink(conn, req,
6884                                                          pdata, total_data,
6885                                                          fname);
6886                         break;
6887                 }
6888
6889                 case SMB_FILE_RENAME_INFORMATION:
6890                 {
6891                         status = smb_file_rename_information(conn, req,
6892                                                              pdata, total_data,
6893                                                              fsp, fname);
6894                         break;
6895                 }
6896
6897 #if defined(HAVE_POSIX_ACLS)
6898                 case SMB_SET_POSIX_ACL:
6899                 {
6900                         status = smb_set_posix_acl(conn,
6901                                                 pdata,
6902                                                 total_data,
6903                                                 fsp,
6904                                                 fname,
6905                                                 &sbuf);
6906                         break;
6907                 }
6908 #endif
6909
6910                 case SMB_SET_POSIX_LOCK:
6911                 {
6912                         if (tran_call != TRANSACT2_SETFILEINFO) {
6913                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6914                                 return;
6915                         }
6916                         status = smb_set_posix_lock(conn, req,
6917                                                     pdata, total_data, fsp);
6918                         break;
6919                 }
6920
6921                 case SMB_POSIX_PATH_OPEN:
6922                 {
6923                         if (tran_call != TRANSACT2_SETPATHINFO) {
6924                                 /* We must have a pathname for this. */
6925                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6926                                 return;
6927                         }
6928
6929                         status = smb_posix_open(conn, req,
6930                                                 ppdata,
6931                                                 total_data,
6932                                                 fname,
6933                                                 &sbuf,
6934                                                 &data_return_size);
6935                         break;
6936                 }
6937
6938                 case SMB_POSIX_PATH_UNLINK:
6939                 {
6940                         if (tran_call != TRANSACT2_SETPATHINFO) {
6941                                 /* We must have a pathname for this. */
6942                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6943                                 return;
6944                         }
6945
6946                         status = smb_posix_unlink(conn, req,
6947                                                 pdata,
6948                                                 total_data,
6949                                                 fname,
6950                                                 &sbuf);
6951                         break;
6952                 }
6953
6954                 default:
6955                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6956                         return;
6957         }
6958
6959         
6960         if (!NT_STATUS_IS_OK(status)) {
6961                 if (open_was_deferred(req->mid)) {
6962                         /* We have re-scheduled this call. */
6963                         return;
6964                 }
6965                 if (blocking_lock_was_deferred(req->mid)) {
6966                         /* We have re-scheduled this call. */
6967                         return;
6968                 }
6969                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6970                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6971                                         ERRSRV, ERRbadpath);
6972                         return;
6973                 }
6974                 if (info_level == SMB_POSIX_PATH_OPEN) {
6975                         reply_openerror(req, status);
6976                         return;
6977                 }
6978
6979                 reply_nterror(req, status);
6980                 return;
6981         }
6982
6983         SSVAL(params,0,0);
6984         send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6985                             max_data_bytes);
6986   
6987         return;
6988 }
6989
6990 /****************************************************************************
6991  Reply to a TRANS2_MKDIR (make directory with extended attributes).
6992 ****************************************************************************/
6993
6994 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6995                              char **pparams, int total_params,
6996                              char **ppdata, int total_data,
6997                              unsigned int max_data_bytes)
6998 {
6999         char *params = *pparams;
7000         char *pdata = *ppdata;
7001         char *directory = NULL;
7002         SMB_STRUCT_STAT sbuf;
7003         NTSTATUS status = NT_STATUS_OK;
7004         struct ea_list *ea_list = NULL;
7005         TALLOC_CTX *ctx = talloc_tos();
7006
7007         if (!CAN_WRITE(conn)) {
7008                 reply_doserror(req, ERRSRV, ERRaccess);
7009                 return;
7010         }
7011
7012         if (total_params < 5) {
7013                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7014                 return;
7015         }
7016
7017         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7018                         total_params - 4, STR_TERMINATE,
7019                         &status);
7020         if (!NT_STATUS_IS_OK(status)) {
7021                 reply_nterror(req, status);
7022                 return;
7023         }
7024
7025         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7026
7027         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7028         if (!NT_STATUS_IS_OK(status)) {
7029                 reply_nterror(req, status);
7030                 return;
7031         }
7032
7033         status = check_name(conn, directory);
7034         if (!NT_STATUS_IS_OK(status)) {
7035                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7036                 reply_nterror(req, status);
7037                 return;
7038         }
7039
7040         /* Any data in this call is an EA list. */
7041         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7042                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7043                 return;
7044         }
7045
7046         /*
7047          * OS/2 workplace shell seems to send SET_EA requests of "null"
7048          * length (4 bytes containing IVAL 4).
7049          * They seem to have no effect. Bug #3212. JRA.
7050          */
7051
7052         if (total_data != 4) {
7053                 if (total_data < 10) {
7054                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7055                         return;
7056                 }
7057
7058                 if (IVAL(pdata,0) > total_data) {
7059                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7060                                 IVAL(pdata,0), (unsigned int)total_data));
7061                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7062                         return;
7063                 }
7064
7065                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7066                                        total_data - 4);
7067                 if (!ea_list) {
7068                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7069                         return;
7070                 }
7071         }
7072         /* If total_data == 4 Windows doesn't care what values
7073          * are placed in that field, it just ignores them.
7074          * The System i QNTC IBM SMB client puts bad values here,
7075          * so ignore them. */
7076
7077         status = create_directory(conn, req, directory);
7078
7079         if (!NT_STATUS_IS_OK(status)) {
7080                 reply_nterror(req, status);
7081                 return;
7082         }
7083   
7084         /* Try and set any given EA. */
7085         if (ea_list) {
7086                 status = set_ea(conn, NULL, directory, ea_list);
7087                 if (!NT_STATUS_IS_OK(status)) {
7088                         reply_nterror(req, status);
7089                         return;
7090                 }
7091         }
7092
7093         /* Realloc the parameter and data sizes */
7094         *pparams = (char *)SMB_REALLOC(*pparams,2);
7095         if(*pparams == NULL) {
7096                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7097                 return;
7098         }
7099         params = *pparams;
7100
7101         SSVAL(params,0,0);
7102
7103         send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7104   
7105         return;
7106 }
7107
7108 /****************************************************************************
7109  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7110  We don't actually do this - we just send a null response.
7111 ****************************************************************************/
7112
7113 static void call_trans2findnotifyfirst(connection_struct *conn,
7114                                        struct smb_request *req,
7115                                        char **pparams, int total_params,
7116                                        char **ppdata, int total_data,
7117                                        unsigned int max_data_bytes)
7118 {
7119         static uint16 fnf_handle = 257;
7120         char *params = *pparams;
7121         uint16 info_level;
7122
7123         if (total_params < 6) {
7124                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7125                 return;
7126         }
7127
7128         info_level = SVAL(params,4);
7129         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7130
7131         switch (info_level) {
7132                 case 1:
7133                 case 2:
7134                         break;
7135                 default:
7136                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7137                         return;
7138         }
7139
7140         /* Realloc the parameter and data sizes */
7141         *pparams = (char *)SMB_REALLOC(*pparams,6);
7142         if (*pparams == NULL) {
7143                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7144                 return;
7145         }
7146         params = *pparams;
7147
7148         SSVAL(params,0,fnf_handle);
7149         SSVAL(params,2,0); /* No changes */
7150         SSVAL(params,4,0); /* No EA errors */
7151
7152         fnf_handle++;
7153
7154         if(fnf_handle == 0)
7155                 fnf_handle = 257;
7156
7157         send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7158   
7159         return;
7160 }
7161
7162 /****************************************************************************
7163  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
7164  changes). Currently this does nothing.
7165 ****************************************************************************/
7166
7167 static void call_trans2findnotifynext(connection_struct *conn,
7168                                       struct smb_request *req,
7169                                       char **pparams, int total_params,
7170                                       char **ppdata, int total_data,
7171                                       unsigned int max_data_bytes)
7172 {
7173         char *params = *pparams;
7174
7175         DEBUG(3,("call_trans2findnotifynext\n"));
7176
7177         /* Realloc the parameter and data sizes */
7178         *pparams = (char *)SMB_REALLOC(*pparams,4);
7179         if (*pparams == NULL) {
7180                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7181                 return;
7182         }
7183         params = *pparams;
7184
7185         SSVAL(params,0,0); /* No changes */
7186         SSVAL(params,2,0); /* No EA errors */
7187
7188         send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7189   
7190         return;
7191 }
7192
7193 /****************************************************************************
7194  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7195 ****************************************************************************/
7196
7197 static void call_trans2getdfsreferral(connection_struct *conn,
7198                                       struct smb_request *req,
7199                                       char **pparams, int total_params,
7200                                       char **ppdata, int total_data,
7201                                       unsigned int max_data_bytes)
7202 {
7203         char *params = *pparams;
7204         char *pathname = NULL;
7205         int reply_size = 0;
7206         int max_referral_level;
7207         NTSTATUS status = NT_STATUS_OK;
7208         TALLOC_CTX *ctx = talloc_tos();
7209
7210         DEBUG(10,("call_trans2getdfsreferral\n"));
7211
7212         if (total_params < 3) {
7213                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7214                 return;
7215         }
7216
7217         max_referral_level = SVAL(params,0);
7218
7219         if(!lp_host_msdfs()) {
7220                 reply_doserror(req, ERRDOS, ERRbadfunc);
7221                 return;
7222         }
7223
7224         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7225                     total_params - 2, STR_TERMINATE);
7226         if (!pathname) {
7227                 reply_nterror(req, NT_STATUS_NOT_FOUND);
7228                 return;
7229         }
7230         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7231                                             ppdata,&status)) < 0) {
7232                 reply_nterror(req, status);
7233                 return;
7234         }
7235
7236         SSVAL(req->inbuf, smb_flg2,
7237               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7238         send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7239
7240         return;
7241 }
7242
7243 #define LMCAT_SPL       0x53
7244 #define LMFUNC_GETJOBID 0x60
7245
7246 /****************************************************************************
7247  Reply to a TRANS2_IOCTL - used for OS/2 printing.
7248 ****************************************************************************/
7249
7250 static void call_trans2ioctl(connection_struct *conn,
7251                              struct smb_request *req,
7252                              char **pparams, int total_params,
7253                              char **ppdata, int total_data,
7254                              unsigned int max_data_bytes)
7255 {
7256         char *pdata = *ppdata;
7257         files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7258
7259         /* check for an invalid fid before proceeding */
7260
7261         if (!fsp) {
7262                 reply_doserror(req, ERRDOS, ERRbadfid);
7263                 return;
7264         }
7265
7266         if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7267             && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7268                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7269                 if (*ppdata == NULL) {
7270                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7271                         return;
7272                 }
7273                 pdata = *ppdata;
7274
7275                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7276                         CAN ACCEPT THIS IN UNICODE. JRA. */
7277
7278                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
7279                 srvstr_push(pdata, req->flags2, pdata + 2,
7280                             global_myname(), 15,
7281                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7282                 srvstr_push(pdata, req->flags2, pdata+18,
7283                             lp_servicename(SNUM(conn)), 13,
7284                             STR_ASCII|STR_TERMINATE); /* Service name */
7285                 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7286                                     max_data_bytes);
7287                 return;
7288         }
7289
7290         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7291         reply_doserror(req, ERRSRV, ERRerror);
7292 }
7293
7294 /****************************************************************************
7295  Reply to a SMBfindclose (stop trans2 directory search).
7296 ****************************************************************************/
7297
7298 void reply_findclose(struct smb_request *req)
7299 {
7300         int dptr_num;
7301
7302         START_PROFILE(SMBfindclose);
7303
7304         if (req->wct < 1) {
7305                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7306                 END_PROFILE(SMBfindclose);
7307                 return;
7308         }
7309
7310         dptr_num = SVALS(req->vwv+0, 0);
7311
7312         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7313
7314         dptr_close(&dptr_num);
7315
7316         reply_outbuf(req, 0, 0);
7317
7318         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7319
7320         END_PROFILE(SMBfindclose);
7321         return;
7322 }
7323
7324 /****************************************************************************
7325  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7326 ****************************************************************************/
7327
7328 void reply_findnclose(struct smb_request *req)
7329 {
7330         int dptr_num;
7331
7332         START_PROFILE(SMBfindnclose);
7333
7334         if (req->wct < 1) {
7335                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7336                 END_PROFILE(SMBfindnclose);
7337                 return;
7338         }
7339         
7340         dptr_num = SVAL(req->vwv+0, 0);
7341
7342         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7343
7344         /* We never give out valid handles for a 
7345            findnotifyfirst - so any dptr_num is ok here. 
7346            Just ignore it. */
7347
7348         reply_outbuf(req, 0, 0);
7349
7350         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7351
7352         END_PROFILE(SMBfindnclose);
7353         return;
7354 }
7355
7356 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7357                           struct trans_state *state)
7358 {
7359         if (Protocol >= PROTOCOL_NT1) {
7360                 req->flags2 |= 0x40; /* IS_LONG_NAME */
7361                 SSVAL(req->inbuf,smb_flg2,req->flags2);
7362         }
7363
7364         if (conn->encrypt_level == Required && !req->encrypted) {
7365                 if (state->call != TRANSACT2_QFSINFO &&
7366                                 state->call != TRANSACT2_SETFSINFO) {
7367                         DEBUG(0,("handle_trans2: encryption required "
7368                                 "with call 0x%x\n",
7369                                 (unsigned int)state->call));
7370                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7371                         return;
7372                 }
7373         }
7374
7375         /* Now we must call the relevant TRANS2 function */
7376         switch(state->call)  {
7377         case TRANSACT2_OPEN:
7378         {
7379                 START_PROFILE(Trans2_open);
7380                 call_trans2open(conn, req,
7381                                 &state->param, state->total_param,
7382                                 &state->data, state->total_data,
7383                                 state->max_data_return);
7384                 END_PROFILE(Trans2_open);
7385                 break;
7386         }
7387
7388         case TRANSACT2_FINDFIRST:
7389         {
7390                 START_PROFILE(Trans2_findfirst);
7391                 call_trans2findfirst(conn, req,
7392                                      &state->param, state->total_param,
7393                                      &state->data, state->total_data,
7394                                      state->max_data_return);
7395                 END_PROFILE(Trans2_findfirst);
7396                 break;
7397         }
7398
7399         case TRANSACT2_FINDNEXT:
7400         {
7401                 START_PROFILE(Trans2_findnext);
7402                 call_trans2findnext(conn, req,
7403                                     &state->param, state->total_param,
7404                                     &state->data, state->total_data,
7405                                     state->max_data_return);
7406                 END_PROFILE(Trans2_findnext);
7407                 break;
7408         }
7409
7410         case TRANSACT2_QFSINFO:
7411         {
7412                 START_PROFILE(Trans2_qfsinfo);
7413                 call_trans2qfsinfo(conn, req,
7414                                    &state->param, state->total_param,
7415                                    &state->data, state->total_data,
7416                                    state->max_data_return);
7417                 END_PROFILE(Trans2_qfsinfo);
7418             break;
7419         }
7420
7421         case TRANSACT2_SETFSINFO:
7422         {
7423                 START_PROFILE(Trans2_setfsinfo);
7424                 call_trans2setfsinfo(conn, req,
7425                                      &state->param, state->total_param,
7426                                      &state->data, state->total_data,
7427                                      state->max_data_return);
7428                 END_PROFILE(Trans2_setfsinfo);
7429                 break;
7430         }
7431
7432         case TRANSACT2_QPATHINFO:
7433         case TRANSACT2_QFILEINFO:
7434         {
7435                 START_PROFILE(Trans2_qpathinfo);
7436                 call_trans2qfilepathinfo(conn, req, state->call,
7437                                          &state->param, state->total_param,
7438                                          &state->data, state->total_data,
7439                                          state->max_data_return);
7440                 END_PROFILE(Trans2_qpathinfo);
7441                 break;
7442         }
7443
7444         case TRANSACT2_SETPATHINFO:
7445         case TRANSACT2_SETFILEINFO:
7446         {
7447                 START_PROFILE(Trans2_setpathinfo);
7448                 call_trans2setfilepathinfo(conn, req, state->call,
7449                                            &state->param, state->total_param,
7450                                            &state->data, state->total_data,
7451                                            state->max_data_return);
7452                 END_PROFILE(Trans2_setpathinfo);
7453                 break;
7454         }
7455
7456         case TRANSACT2_FINDNOTIFYFIRST:
7457         {
7458                 START_PROFILE(Trans2_findnotifyfirst);
7459                 call_trans2findnotifyfirst(conn, req,
7460                                            &state->param, state->total_param,
7461                                            &state->data, state->total_data,
7462                                            state->max_data_return);
7463                 END_PROFILE(Trans2_findnotifyfirst);
7464                 break;
7465         }
7466
7467         case TRANSACT2_FINDNOTIFYNEXT:
7468         {
7469                 START_PROFILE(Trans2_findnotifynext);
7470                 call_trans2findnotifynext(conn, req,
7471                                           &state->param, state->total_param,
7472                                           &state->data, state->total_data,
7473                                           state->max_data_return);
7474                 END_PROFILE(Trans2_findnotifynext);
7475                 break;
7476         }
7477
7478         case TRANSACT2_MKDIR:
7479         {
7480                 START_PROFILE(Trans2_mkdir);
7481                 call_trans2mkdir(conn, req,
7482                                  &state->param, state->total_param,
7483                                  &state->data, state->total_data,
7484                                  state->max_data_return);
7485                 END_PROFILE(Trans2_mkdir);
7486                 break;
7487         }
7488
7489         case TRANSACT2_GET_DFS_REFERRAL:
7490         {
7491                 START_PROFILE(Trans2_get_dfs_referral);
7492                 call_trans2getdfsreferral(conn, req,
7493                                           &state->param, state->total_param,
7494                                           &state->data, state->total_data,
7495                                           state->max_data_return);
7496                 END_PROFILE(Trans2_get_dfs_referral);
7497                 break;
7498         }
7499
7500         case TRANSACT2_IOCTL:
7501         {
7502                 START_PROFILE(Trans2_ioctl);
7503                 call_trans2ioctl(conn, req,
7504                                  &state->param, state->total_param,
7505                                  &state->data, state->total_data,
7506                                  state->max_data_return);
7507                 END_PROFILE(Trans2_ioctl);
7508                 break;
7509         }
7510
7511         default:
7512                 /* Error in request */
7513                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7514                 reply_doserror(req, ERRSRV,ERRerror);
7515         }
7516 }
7517
7518 /****************************************************************************
7519  Reply to a SMBtrans2.
7520  ****************************************************************************/
7521
7522 void reply_trans2(struct smb_request *req)
7523 {
7524         connection_struct *conn = req->conn;
7525         unsigned int dsoff;
7526         unsigned int dscnt;
7527         unsigned int psoff;
7528         unsigned int pscnt;
7529         unsigned int tran_call;
7530         unsigned int size;
7531         unsigned int av_size;
7532         struct trans_state *state;
7533         NTSTATUS result;
7534
7535         START_PROFILE(SMBtrans2);
7536
7537         if (req->wct < 14) {
7538                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7539                 END_PROFILE(SMBtrans2);
7540                 return;
7541         }
7542
7543         dsoff = SVAL(req->vwv+12, 0);
7544         dscnt = SVAL(req->vwv+11, 0);
7545         psoff = SVAL(req->vwv+10, 0);
7546         pscnt = SVAL(req->vwv+9, 0);
7547         tran_call = SVAL(req->vwv+14, 0);
7548         size = smb_len(req->inbuf) + 4;
7549         av_size = smb_len(req->inbuf);
7550
7551         result = allow_new_trans(conn->pending_trans, req->mid);
7552         if (!NT_STATUS_IS_OK(result)) {
7553                 DEBUG(2, ("Got invalid trans2 request: %s\n",
7554                           nt_errstr(result)));
7555                 reply_nterror(req, result);
7556                 END_PROFILE(SMBtrans2);
7557                 return;
7558         }
7559
7560         if (IS_IPC(conn)) {
7561                 switch (tran_call) {
7562                 /* List the allowed trans2 calls on IPC$ */
7563                 case TRANSACT2_OPEN:
7564                 case TRANSACT2_GET_DFS_REFERRAL:
7565                 case TRANSACT2_QFILEINFO:
7566                 case TRANSACT2_QFSINFO:
7567                 case TRANSACT2_SETFSINFO:
7568                         break;
7569                 default:
7570                         reply_doserror(req, ERRSRV, ERRaccess);
7571                         END_PROFILE(SMBtrans2);
7572                         return;
7573                 }
7574         }
7575
7576         if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7577                 DEBUG(0, ("talloc failed\n"));
7578                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7579                 END_PROFILE(SMBtrans2);
7580                 return;
7581         }
7582
7583         state->cmd = SMBtrans2;
7584
7585         state->mid = req->mid;
7586         state->vuid = req->vuid;
7587         state->setup_count = SVAL(req->vwv+13, 0);
7588         state->setup = NULL;
7589         state->total_param = SVAL(req->vwv+0, 0);
7590         state->param = NULL;
7591         state->total_data =  SVAL(req->vwv+1, 0);
7592         state->data = NULL;
7593         state->max_param_return = SVAL(req->vwv+2, 0);
7594         state->max_data_return  = SVAL(req->vwv+3, 0);
7595         state->max_setup_return = SVAL(req->vwv+4, 0);
7596         state->close_on_completion = BITSETW(req->vwv+5, 0);
7597         state->one_way = BITSETW(req->vwv+5, 1);
7598
7599         state->call = tran_call;
7600
7601         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7602            is so as a sanity check */
7603         if (state->setup_count != 1) {
7604                 /*
7605                  * Need to have rc=0 for ioctl to get job id for OS/2.
7606                  *  Network printing will fail if function is not successful.
7607                  *  Similar function in reply.c will be used if protocol
7608                  *  is LANMAN1.0 instead of LM1.2X002.
7609                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
7610                  *  outbuf doesn't have to be set(only job id is used).
7611                  */
7612                 if ( (state->setup_count == 4)
7613                      && (tran_call == TRANSACT2_IOCTL)
7614                      && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7615                      && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7616                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7617                 } else {
7618                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7619                         DEBUG(2,("Transaction is %d\n",tran_call));
7620                         TALLOC_FREE(state);
7621                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7622                         END_PROFILE(SMBtrans2);
7623                         return;
7624                 }
7625         }
7626
7627         if ((dscnt > state->total_data) || (pscnt > state->total_param))
7628                 goto bad_param;
7629
7630         if (state->total_data) {
7631                 /* Can't use talloc here, the core routines do realloc on the
7632                  * params and data. */
7633                 state->data = (char *)SMB_MALLOC(state->total_data);
7634                 if (state->data == NULL) {
7635                         DEBUG(0,("reply_trans2: data malloc fail for %u "
7636                                  "bytes !\n", (unsigned int)state->total_data));
7637                         TALLOC_FREE(state);
7638                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7639                         END_PROFILE(SMBtrans2);
7640                         return;
7641                 }
7642
7643                 if (dscnt > state->total_data ||
7644                                 dsoff+dscnt < dsoff) {
7645                         goto bad_param;
7646                 }
7647
7648                 if (dsoff > av_size ||
7649                                 dscnt > av_size ||
7650                                 dsoff+dscnt > av_size) {
7651                         goto bad_param;
7652                 }
7653
7654                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7655         }
7656
7657         if (state->total_param) {
7658                 /* Can't use talloc here, the core routines do realloc on the
7659                  * params and data. */
7660                 state->param = (char *)SMB_MALLOC(state->total_param);
7661                 if (state->param == NULL) {
7662                         DEBUG(0,("reply_trans: param malloc fail for %u "
7663                                  "bytes !\n", (unsigned int)state->total_param));
7664                         SAFE_FREE(state->data);
7665                         TALLOC_FREE(state);
7666                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7667                         END_PROFILE(SMBtrans2);
7668                         return;
7669                 } 
7670
7671                 if (pscnt > state->total_param ||
7672                                 psoff+pscnt < psoff) {
7673                         goto bad_param;
7674                 }
7675
7676                 if (psoff > av_size ||
7677                                 pscnt > av_size ||
7678                                 psoff+pscnt > av_size) {
7679                         goto bad_param;
7680                 }
7681
7682                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7683         }
7684
7685         state->received_data  = dscnt;
7686         state->received_param = pscnt;
7687
7688         if ((state->received_param == state->total_param) &&
7689             (state->received_data == state->total_data)) {
7690
7691                 handle_trans2(conn, req, state);
7692
7693                 SAFE_FREE(state->data);
7694                 SAFE_FREE(state->param);
7695                 TALLOC_FREE(state);
7696                 END_PROFILE(SMBtrans2);
7697                 return;
7698         }
7699
7700         DLIST_ADD(conn->pending_trans, state);
7701
7702         /* We need to send an interim response then receive the rest
7703            of the parameter/data bytes */
7704         reply_outbuf(req, 0, 0);
7705         show_msg((char *)req->outbuf);
7706         END_PROFILE(SMBtrans2);
7707         return;
7708
7709   bad_param:
7710
7711         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7712         SAFE_FREE(state->data);
7713         SAFE_FREE(state->param);
7714         TALLOC_FREE(state);
7715         END_PROFILE(SMBtrans2);
7716         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7717 }
7718
7719
7720 /****************************************************************************
7721  Reply to a SMBtranss2
7722  ****************************************************************************/
7723
7724 void reply_transs2(struct smb_request *req)
7725 {
7726         connection_struct *conn = req->conn;
7727         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7728         struct trans_state *state;
7729         unsigned int size;
7730         unsigned int av_size;
7731
7732         START_PROFILE(SMBtranss2);
7733
7734         show_msg((char *)req->inbuf);
7735
7736         if (req->wct < 8) {
7737                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7738                 END_PROFILE(SMBtranss2);
7739                 return;
7740         }
7741
7742         size = smb_len(req->inbuf)+4;
7743         av_size = smb_len(req->inbuf);
7744
7745         for (state = conn->pending_trans; state != NULL;
7746              state = state->next) {
7747                 if (state->mid == req->mid) {
7748                         break;
7749                 }
7750         }
7751
7752         if ((state == NULL) || (state->cmd != SMBtrans2)) {
7753                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7754                 END_PROFILE(SMBtranss2);
7755                 return;
7756         }
7757
7758         /* Revise state->total_param and state->total_data in case they have
7759            changed downwards */
7760
7761         if (SVAL(req->vwv+0, 0) < state->total_param)
7762                 state->total_param = SVAL(req->vwv+0, 0);
7763         if (SVAL(req->vwv+1, 0) < state->total_data)
7764                 state->total_data = SVAL(req->vwv+1, 0);
7765
7766         pcnt = SVAL(req->vwv+2, 0);
7767         poff = SVAL(req->vwv+3, 0);
7768         pdisp = SVAL(req->vwv+4, 0);
7769
7770         dcnt = SVAL(req->vwv+5, 0);
7771         doff = SVAL(req->vwv+6, 0);
7772         ddisp = SVAL(req->vwv+7, 0);
7773
7774         state->received_param += pcnt;
7775         state->received_data += dcnt;
7776                 
7777         if ((state->received_data > state->total_data) ||
7778             (state->received_param > state->total_param))
7779                 goto bad_param;
7780
7781         if (pcnt) {
7782                 if (pdisp > state->total_param ||
7783                                 pcnt > state->total_param ||
7784                                 pdisp+pcnt > state->total_param ||
7785                                 pdisp+pcnt < pdisp) {
7786                         goto bad_param;
7787                 }
7788
7789                 if (poff > av_size ||
7790                                 pcnt > av_size ||
7791                                 poff+pcnt > av_size ||
7792                                 poff+pcnt < poff) {
7793                         goto bad_param;
7794                 }
7795
7796                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7797                        pcnt);
7798         }
7799
7800         if (dcnt) {
7801                 if (ddisp > state->total_data ||
7802                                 dcnt > state->total_data ||
7803                                 ddisp+dcnt > state->total_data ||
7804                                 ddisp+dcnt < ddisp) {
7805                         goto bad_param;
7806                 }
7807
7808                 if (ddisp > av_size ||
7809                                 dcnt > av_size ||
7810                                 ddisp+dcnt > av_size ||
7811                                 ddisp+dcnt < ddisp) {
7812                         goto bad_param;
7813                 }
7814
7815                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7816                        dcnt);      
7817         }
7818
7819         if ((state->received_param < state->total_param) ||
7820             (state->received_data < state->total_data)) {
7821                 END_PROFILE(SMBtranss2);
7822                 return;
7823         }
7824
7825         /*
7826          * construct_reply_common will copy smb_com from inbuf to
7827          * outbuf. SMBtranss2 is wrong here.
7828          */
7829         SCVAL(req->inbuf,smb_com,SMBtrans2);
7830
7831         handle_trans2(conn, req, state);
7832
7833         DLIST_REMOVE(conn->pending_trans, state);
7834         SAFE_FREE(state->data);
7835         SAFE_FREE(state->param);
7836         TALLOC_FREE(state);
7837
7838         END_PROFILE(SMBtranss2);
7839         return;
7840
7841   bad_param:
7842
7843         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7844         DLIST_REMOVE(conn->pending_trans, state);
7845         SAFE_FREE(state->data);
7846         SAFE_FREE(state->param);
7847         TALLOC_FREE(state);
7848         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7849         END_PROFILE(SMBtranss2);
7850         return;
7851 }