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