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