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