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