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