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