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