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