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