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