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