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