r5720: Attempt to fix bug #2382 (Excel shared workbook stops working). Also
[kai/samba.git] / source3 / smbd / trans2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2003
5    Copyright (C) Stefan (metze) Metzmacher      2003
6
7    Extensively modified by Andrew Tridgell, 1995
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 extern enum protocol_types Protocol;
27 extern int smb_read_error;
28 extern int global_oplock_break;
29 extern uint32 global_client_caps;
30 extern struct current_user current_user;
31
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
34
35 /********************************************************************
36  Roundup a value to the nearest allocation roundup size boundary.
37  Only do this for Windows clients.
38 ********************************************************************/
39
40 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
41 {
42         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
43
44         /* Only roundup for Windows clients. */
45         enum remote_arch_types ra_type = get_remote_arch();
46         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
47                 val = SMB_ROUNDUP(val,rval);
48         }
49         return val;
50 }
51
52 /********************************************************************
53  Given a stat buffer return the allocated size on disk, taking into
54  account sparse files.
55 ********************************************************************/
56
57 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
58 {
59         SMB_BIG_UINT ret;
60
61 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
62         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
63 #else
64         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
65 #endif
66
67         if (!ret && fsp && fsp->initial_allocation_size)
68                 ret = fsp->initial_allocation_size;
69
70         return smb_roundup(conn, ret);
71 }
72
73 /****************************************************************************
74  Utility functions for dealing with extended attributes.
75 ****************************************************************************/
76
77 static const char *prohibited_ea_names[] = {
78         SAMBA_POSIX_INHERITANCE_EA_NAME,
79         SAMBA_XATTR_DOS_ATTRIB,
80         NULL
81 };
82
83 /****************************************************************************
84  Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
86
87 static BOOL samba_private_attr_name(const char *unix_ea_name)
88 {
89         int i;
90
91         for (i = 0; prohibited_ea_names[i]; i++) {
92                 if (strequal( prohibited_ea_names[i], unix_ea_name))
93                         return True;
94         }
95         return False;
96 }
97
98 struct ea_list {
99         struct ea_list *next, *prev;
100         struct ea_struct ea;
101 };
102
103 /****************************************************************************
104  Get one EA value. Fill in a struct ea_struct.
105 ****************************************************************************/
106
107 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
108                                 const char *fname, char *ea_name, struct ea_struct *pea)
109 {
110         /* Get the value of this xattr. Max size is 64k. */
111         size_t attr_size = 256;
112         char *val = NULL;
113         ssize_t sizeret;
114
115  again:
116
117         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
118         if (!val) {
119                 return False;
120         }
121
122         if (fsp && fsp->fd != -1) {
123                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
124         } else {
125                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
126         }
127
128         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
129                 attr_size = 65536;
130                 goto again;
131         }
132
133         if (sizeret == -1) {
134                 return False;
135         }
136
137         DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
138         dump_data(10, val, sizeret);
139
140         pea->flags = 0;
141         if (strnequal(ea_name, "user.", 5)) {
142                 pea->name = &ea_name[5];
143         } else {
144                 pea->name = ea_name;
145         }
146         pea->value.data = 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.
1489          */
1490
1491         if(numentries == 0) {
1492                 dptr_close(&dptr_num);
1493                 return ERROR_DOS(ERRDOS,ERRbadfile);
1494         }
1495
1496         /* At this point pdata points to numentries directory entries. */
1497
1498         /* Set up the return parameter block */
1499         SSVAL(params,0,dptr_num);
1500         SSVAL(params,2,numentries);
1501         SSVAL(params,4,finished);
1502         SSVAL(params,6,0); /* Never an EA error */
1503         SSVAL(params,8,last_entry_off);
1504
1505         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1506
1507         if ((! *directory) && dptr_path(dptr_num))
1508                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1509
1510         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1511                 smb_fn_name(CVAL(inbuf,smb_com)), 
1512                 mask, directory, dirtype, numentries ) );
1513
1514         /* 
1515          * Force a name mangle here to ensure that the
1516          * mask as an 8.3 name is top of the mangled cache.
1517          * The reasons for this are subtle. Don't remove
1518          * this code unless you know what you are doing
1519          * (see PR#13758). JRA.
1520          */
1521
1522         if(!mangle_is_8_3_wildcards( mask, False))
1523                 mangle_map(mask, True, True, SNUM(conn));
1524
1525         return(-1);
1526 }
1527
1528 /****************************************************************************
1529  Reply to a TRANS2_FINDNEXT.
1530 ****************************************************************************/
1531
1532 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1533                                         char **pparams, int total_params, char **ppdata, int total_data,
1534                                         unsigned int max_data_bytes)
1535 {
1536         /* We must be careful here that we don't return more than the
1537                 allowed number of data bytes. If this means returning fewer than
1538                 maxentries then so be it. We assume that the redirector has
1539                 enough room for the fixed number of parameter bytes it has
1540                 requested. */
1541         char *params = *pparams;
1542         char *pdata = *ppdata;
1543         int dptr_num = SVAL(params,0);
1544         int maxentries = SVAL(params,2);
1545         uint16 info_level = SVAL(params,4);
1546         uint32 resume_key = IVAL(params,6);
1547         uint16 findnext_flags = SVAL(params,10);
1548         BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1549         BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1550         BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1551         BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1552         pstring resume_name;
1553         pstring mask;
1554         pstring directory;
1555         char *p;
1556         uint16 dirtype;
1557         int numentries = 0;
1558         int i, last_entry_off=0;
1559         BOOL finished = False;
1560         BOOL dont_descend = False;
1561         BOOL out_of_space = False;
1562         int space_remaining;
1563         NTSTATUS ntstatus = NT_STATUS_OK;
1564
1565         if (total_params < 12)
1566                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1567
1568         *mask = *directory = *resume_name = 0;
1569
1570         srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1571         if (!NT_STATUS_IS_OK(ntstatus)) {
1572                 return ERROR_NT(ntstatus);
1573         }
1574
1575         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1576 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1577 resume_key = %d resume name = %s continue=%d level = %d\n",
1578                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1579                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1580
1581         if (!maxentries) {
1582                 /* W2K3 seems to treat zero as 1. */
1583                 maxentries = 1;
1584         }
1585
1586         switch (info_level) {
1587                 case SMB_INFO_STANDARD:
1588                 case SMB_INFO_QUERY_EA_SIZE:
1589                 case SMB_FIND_FILE_DIRECTORY_INFO:
1590                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1591                 case SMB_FIND_FILE_NAMES_INFO:
1592                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1593                         break;
1594                 case SMB_FIND_FILE_UNIX:
1595                         if (!lp_unix_extensions())
1596                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1597                         break;
1598                 default:
1599                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1600         }
1601
1602         pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1603         if(pdata == NULL)
1604                 return ERROR_DOS(ERRDOS,ERRnomem);
1605
1606         *ppdata = pdata;
1607         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1608
1609         /* Realloc the params space */
1610         params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1611         if( params == NULL )
1612                 return ERROR_DOS(ERRDOS,ERRnomem);
1613
1614         *pparams = params;
1615
1616         /* Check that the dptr is valid */
1617         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1618                 return ERROR_DOS(ERRDOS,ERRnofiles);
1619
1620         string_set(&conn->dirpath,dptr_path(dptr_num));
1621
1622         /* Get the wildcard mask from the dptr */
1623         if((p = dptr_wcard(dptr_num))== NULL) {
1624                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1625                 return ERROR_DOS(ERRDOS,ERRnofiles);
1626         }
1627
1628         pstrcpy(mask, p);
1629         pstrcpy(directory,conn->dirpath);
1630
1631         /* Get the attr mask from the dptr */
1632         dirtype = dptr_attr(dptr_num);
1633
1634         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1635                 dptr_num, mask, dirtype, 
1636                 (long)conn->dirptr,
1637                 dptr_TellDir(conn->dirptr)));
1638
1639         /* We don't need to check for VOL here as this is returned by 
1640                 a different TRANS2 call. */
1641
1642         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1643         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1644                 dont_descend = True;
1645     
1646         p = pdata;
1647         space_remaining = max_data_bytes;
1648         out_of_space = False;
1649
1650         /* 
1651          * Seek to the correct position. We no longer use the resume key but
1652          * depend on the last file name instead.
1653          */
1654
1655         if(*resume_name && !continue_bit) {
1656                 SMB_STRUCT_STAT st;
1657
1658                 long current_pos = 0;
1659                 /*
1660                  * Remember, mangle_map is called by
1661                  * get_lanman2_dir_entry(), so the resume name
1662                  * could be mangled. Ensure we check the unmangled name.
1663                  */
1664
1665                 if (mangle_is_mangled(resume_name)) {
1666                         mangle_check_cache(resume_name, sizeof(resume_name)-1);
1667                 }
1668
1669                 /*
1670                  * Fix for NT redirector problem triggered by resume key indexes
1671                  * changing between directory scans. We now return a resume key of 0
1672                  * and instead look for the filename to continue from (also given
1673                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1674                  * findfirst/findnext (as is usual) then the directory pointer
1675                  * should already be at the correct place.
1676                  */
1677
1678                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
1679         } /* end if resume_name && !continue_bit */
1680
1681         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1682                 BOOL got_exact_match = False;
1683
1684                 /* this is a heuristic to avoid seeking the dirptr except when 
1685                         absolutely necessary. It allows for a filename of about 40 chars */
1686                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1687                         out_of_space = True;
1688                         finished = False;
1689                 } else {
1690                         finished = !get_lanman2_dir_entry(conn,
1691                                                 inbuf, outbuf,
1692                                                 mask,dirtype,info_level,
1693                                                 requires_resume_key,dont_descend,
1694                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1695                                                 &last_entry_off);
1696                 }
1697
1698                 if (finished && out_of_space)
1699                         finished = False;
1700
1701                 if (!finished && !out_of_space)
1702                         numentries++;
1703
1704                 /*
1705                  * As an optimisation if we know we aren't looking
1706                  * for a wildcard name (ie. the name matches the wildcard exactly)
1707                  * then we can finish on any (first) match.
1708                  * This speeds up large directory searches. JRA.
1709                  */
1710
1711                 if(got_exact_match)
1712                         finished = True;
1713
1714                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1715         }
1716   
1717         /* Check if we can close the dirptr */
1718         if(close_after_request || (finished && close_if_end)) {
1719                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1720                 dptr_close(&dptr_num); /* This frees up the saved mask */
1721         }
1722
1723         /* Set up the return parameter block */
1724         SSVAL(params,0,numentries);
1725         SSVAL(params,2,finished);
1726         SSVAL(params,4,0); /* Never an EA error */
1727         SSVAL(params,6,last_entry_off);
1728
1729         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1730
1731         if ((! *directory) && dptr_path(dptr_num))
1732                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1733
1734         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1735                 smb_fn_name(CVAL(inbuf,smb_com)), 
1736                 mask, directory, dirtype, numentries ) );
1737
1738         return(-1);
1739 }
1740
1741 /****************************************************************************
1742  Reply to a TRANS2_QFSINFO (query filesystem info).
1743 ****************************************************************************/
1744
1745 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1746                                         char **pparams, int total_params, char **ppdata, int total_data,
1747                                         unsigned int max_data_bytes)
1748 {
1749         char *pdata = *ppdata;
1750         char *params = *pparams;
1751         uint16 info_level = SVAL(params,0);
1752         int data_len, len;
1753         SMB_STRUCT_STAT st;
1754         char *vname = volume_label(SNUM(conn));
1755         int snum = SNUM(conn);
1756         char *fstype = lp_fstype(SNUM(conn));
1757         int quota_flag = 0;
1758
1759         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1760
1761         if(SMB_VFS_STAT(conn,".",&st)!=0) {
1762                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1763                 return ERROR_DOS(ERRSRV,ERRinvdevice);
1764         }
1765
1766         pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1767         if ( pdata == NULL )
1768                 return ERROR_DOS(ERRDOS,ERRnomem);
1769
1770         *ppdata = pdata;
1771         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1772
1773         switch (info_level) {
1774                 case SMB_INFO_ALLOCATION:
1775                 {
1776                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1777                         data_len = 18;
1778                         SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); 
1779                         block_size = lp_block_size(snum);
1780                         if (bsize < block_size) {
1781                                 SMB_BIG_UINT factor = block_size/bsize;
1782                                 bsize = block_size;
1783                                 dsize /= factor;
1784                                 dfree /= factor;
1785                         }
1786                         if (bsize > block_size) {
1787                                 SMB_BIG_UINT factor = bsize/block_size;
1788                                 bsize = block_size;
1789                                 dsize *= factor;
1790                                 dfree *= factor;
1791                         }
1792                         bytes_per_sector = 512;
1793                         sectors_per_unit = bsize/bytes_per_sector;
1794
1795                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1796 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1797                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1798
1799                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
1800                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1801                         SIVAL(pdata,l1_cUnit,dsize);
1802                         SIVAL(pdata,l1_cUnitAvail,dfree);
1803                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
1804                         break;
1805                 }
1806
1807                 case SMB_INFO_VOLUME:
1808                         /* Return volume name */
1809                         /* 
1810                          * Add volume serial number - hash of a combination of
1811                          * the called hostname and the service name.
1812                          */
1813                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
1814                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1815                         SCVAL(pdata,l2_vol_cch,len);
1816                         data_len = l2_vol_szVolLabel + len;
1817                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1818                                 (unsigned)st.st_ctime, len, vname));
1819                         break;
1820
1821                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1822                 case SMB_FS_ATTRIBUTE_INFORMATION:
1823
1824
1825 #if defined(HAVE_SYS_QUOTAS)
1826                         quota_flag = FILE_VOLUME_QUOTAS;
1827 #endif
1828
1829                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1830                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1831                                 quota_flag); /* FS ATTRIBUTES */
1832
1833                         SIVAL(pdata,4,255); /* Max filename component length */
1834                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1835                                 and will think we can't do long filenames */
1836                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1837                         SIVAL(pdata,8,len);
1838                         data_len = 12 + len;
1839                         break;
1840
1841                 case SMB_QUERY_FS_LABEL_INFO:
1842                 case SMB_FS_LABEL_INFORMATION:
1843                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1844                         data_len = 4 + len;
1845                         SIVAL(pdata,0,len);
1846                         break;
1847
1848                 case SMB_QUERY_FS_VOLUME_INFO:      
1849                 case SMB_FS_VOLUME_INFORMATION:
1850
1851                         /* 
1852                          * Add volume serial number - hash of a combination of
1853                          * the called hostname and the service name.
1854                          */
1855                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1856                                 (str_checksum(get_local_machine_name())<<16));
1857
1858                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1859                         SIVAL(pdata,12,len);
1860                         data_len = 18+len;
1861                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
1862                                 (int)strlen(vname),vname, lp_servicename(snum)));
1863                         break;
1864
1865                 case SMB_QUERY_FS_SIZE_INFO:
1866                 case SMB_FS_SIZE_INFORMATION:
1867                 {
1868                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1869                         data_len = 24;
1870                         SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1871                         block_size = lp_block_size(snum);
1872                         if (bsize < block_size) {
1873                                 SMB_BIG_UINT factor = block_size/bsize;
1874                                 bsize = block_size;
1875                                 dsize /= factor;
1876                                 dfree /= factor;
1877                         }
1878                         if (bsize > block_size) {
1879                                 SMB_BIG_UINT factor = bsize/block_size;
1880                                 bsize = block_size;
1881                                 dsize *= factor;
1882                                 dfree *= factor;
1883                         }
1884                         bytes_per_sector = 512;
1885                         sectors_per_unit = bsize/bytes_per_sector;
1886                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1887 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1888                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1889                         SBIG_UINT(pdata,0,dsize);
1890                         SBIG_UINT(pdata,8,dfree);
1891                         SIVAL(pdata,16,sectors_per_unit);
1892                         SIVAL(pdata,20,bytes_per_sector);
1893                         break;
1894                 }
1895
1896                 case SMB_FS_FULL_SIZE_INFORMATION:
1897                 {
1898                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1899                         data_len = 32;
1900                         SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1901                         block_size = lp_block_size(snum);
1902                         if (bsize < block_size) {
1903                                 SMB_BIG_UINT factor = block_size/bsize;
1904                                 bsize = block_size;
1905                                 dsize /= factor;
1906                                 dfree /= factor;
1907                         }
1908                         if (bsize > block_size) {
1909                                 SMB_BIG_UINT factor = bsize/block_size;
1910                                 bsize = block_size;
1911                                 dsize *= factor;
1912                                 dfree *= factor;
1913                         }
1914                         bytes_per_sector = 512;
1915                         sectors_per_unit = bsize/bytes_per_sector;
1916                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1917 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1918                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1919                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1920                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1921                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1922                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1923                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1924                         break;
1925                 }
1926
1927                 case SMB_QUERY_FS_DEVICE_INFO:
1928                 case SMB_FS_DEVICE_INFORMATION:
1929                         data_len = 8;
1930                         SIVAL(pdata,0,0); /* dev type */
1931                         SIVAL(pdata,4,0); /* characteristics */
1932                         break;
1933
1934 #ifdef HAVE_SYS_QUOTAS
1935                 case SMB_FS_QUOTA_INFORMATION:
1936                 /* 
1937                  * what we have to send --metze:
1938                  *
1939                  * Unknown1:            24 NULL bytes
1940                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1941                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
1942                  * Quota Flags:         2 byte :
1943                  * Unknown3:            6 NULL bytes
1944                  *
1945                  * 48 bytes total
1946                  * 
1947                  * details for Quota Flags:
1948                  * 
1949                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1950                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
1951                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1952                  * 0x0001 Enable Quotas: enable quota for this fs
1953                  *
1954                  */
1955                 {
1956                         /* we need to fake up a fsp here,
1957                          * because its not send in this call
1958                          */
1959                         files_struct fsp;
1960                         SMB_NTQUOTA_STRUCT quotas;
1961                         
1962                         ZERO_STRUCT(fsp);
1963                         ZERO_STRUCT(quotas);
1964                         
1965                         fsp.conn = conn;
1966                         fsp.fnum = -1;
1967                         fsp.fd = -1;
1968                         
1969                         /* access check */
1970                         if (current_user.uid != 0) {
1971                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1972                                         lp_servicename(SNUM(conn)),conn->user));
1973                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1974                         }
1975                         
1976                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1977                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1978                                 return ERROR_DOS(ERRSRV,ERRerror);
1979                         }
1980
1981                         data_len = 48;
1982
1983                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
1984                 
1985                         /* Unknown1 24 NULL bytes*/
1986                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1987                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1988                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1989                 
1990                         /* Default Soft Quota 8 bytes */
1991                         SBIG_UINT(pdata,24,quotas.softlim);
1992
1993                         /* Default Hard Quota 8 bytes */
1994                         SBIG_UINT(pdata,32,quotas.hardlim);
1995         
1996                         /* Quota flag 2 bytes */
1997                         SSVAL(pdata,40,quotas.qflags);
1998                 
1999                         /* Unknown3 6 NULL bytes */
2000                         SSVAL(pdata,42,0);
2001                         SIVAL(pdata,44,0);
2002                         
2003                         break;
2004                 }
2005 #endif /* HAVE_SYS_QUOTAS */
2006                 case SMB_FS_OBJECTID_INFORMATION:
2007                         data_len = 64;
2008                         break;
2009
2010                 /*
2011                  * Query the version and capabilities of the CIFS UNIX extensions
2012                  * in use.
2013                  */
2014
2015                 case SMB_QUERY_CIFS_UNIX_INFO:
2016                         if (!lp_unix_extensions())
2017                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2018                         data_len = 12;
2019                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2020                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2021                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2022                         break;
2023
2024                 case SMB_MAC_QUERY_FS_INFO:
2025                         /*
2026                          * Thursby MAC extension... ONLY on NTFS filesystems
2027                          * once we do streams then we don't need this
2028                          */
2029                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2030                                 data_len = 88;
2031                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2032                                 break;
2033                         }
2034                         /* drop through */
2035                 default:
2036                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2037         }
2038
2039
2040         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2041
2042         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2043
2044         return -1;
2045 }
2046
2047 #ifdef HAVE_SYS_QUOTAS
2048 /****************************************************************************
2049  Reply to a TRANS2_SETFSINFO (set filesystem info).
2050 ****************************************************************************/
2051
2052 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2053                                         char **pparams, int total_params, char **ppdata, int total_data,
2054                                         unsigned int max_data_bytes)
2055 {
2056         char *pdata = *ppdata;
2057         char *params = *pparams;
2058         files_struct *fsp = NULL;
2059         uint16 info_level;
2060         int outsize;
2061         SMB_NTQUOTA_STRUCT quotas;
2062         
2063         ZERO_STRUCT(quotas);
2064
2065         DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2066
2067         /* access check */
2068         if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2069                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2070                         lp_servicename(SNUM(conn)),conn->user));
2071                 return ERROR_DOS(ERRSRV,ERRaccess);
2072         }
2073
2074         /*  */
2075         if (total_params < 4) {
2076                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2077                         total_params));
2078                 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2079         }
2080
2081         fsp = file_fsp(params,0);
2082
2083         if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2084                 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2085                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2086         }
2087
2088         info_level = SVAL(params,2);
2089
2090         switch(info_level) {
2091                 case SMB_FS_QUOTA_INFORMATION:
2092                         /* note: normaly there're 48 bytes,
2093                          * but we didn't use the last 6 bytes for now 
2094                          * --metze 
2095                          */
2096                         if (total_data < 42) {
2097                                 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2098                                         total_data));
2099                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2100                         }
2101                         
2102                         /* unknown_1 24 NULL bytes in pdata*/
2103                 
2104                         /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2105                         quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2106 #ifdef LARGE_SMB_OFF_T
2107                         quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2108 #else /* LARGE_SMB_OFF_T */
2109                         if ((IVAL(pdata,28) != 0)&&
2110                                 ((quotas.softlim != 0xFFFFFFFF)||
2111                                 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2112                                 /* more than 32 bits? */
2113                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2114                         }
2115 #endif /* LARGE_SMB_OFF_T */
2116                 
2117                         /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2118                         quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2119 #ifdef LARGE_SMB_OFF_T
2120                         quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2121 #else /* LARGE_SMB_OFF_T */
2122                         if ((IVAL(pdata,36) != 0)&&
2123                                 ((quotas.hardlim != 0xFFFFFFFF)||
2124                                 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2125                                 /* more than 32 bits? */
2126                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2127                         }
2128 #endif /* LARGE_SMB_OFF_T */
2129                 
2130                         /* quota_flags 2 bytes **/
2131                         quotas.qflags = SVAL(pdata,40);
2132                 
2133                         /* unknown_2 6 NULL bytes follow*/
2134                 
2135                         /* now set the quotas */
2136                         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2137                                 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2138                                 return ERROR_DOS(ERRSRV,ERRerror);
2139                         }
2140                         
2141                         break;
2142                 default:
2143                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2144                                 info_level));
2145                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2146                         break;
2147         }
2148
2149         /* 
2150          * sending this reply works fine, 
2151          * but I'm not sure it's the same 
2152          * like windows do...
2153          * --metze
2154          */ 
2155         outsize = set_message(outbuf,10,0,True);
2156
2157         return outsize;
2158 }
2159 #endif /* HAVE_SYS_QUOTAS */
2160
2161 /****************************************************************************
2162  Utility function to set bad path error.
2163 ****************************************************************************/
2164
2165 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2166 {
2167         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2168                         err, (int)bad_path ));
2169
2170         if(err == ENOENT) {
2171                 if (bad_path) {
2172                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2173                 } else {
2174                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2175                 }
2176         }
2177         return UNIXERROR(def_class,def_code);
2178 }
2179
2180 #if defined(HAVE_POSIX_ACLS)
2181 /****************************************************************************
2182  Utility function to count the number of entries in a POSIX acl.
2183 ****************************************************************************/
2184
2185 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2186 {
2187         unsigned int ace_count = 0;
2188         int entry_id = SMB_ACL_FIRST_ENTRY;
2189         SMB_ACL_ENTRY_T entry;
2190
2191         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2192                 /* get_next... */
2193                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2194                         entry_id = SMB_ACL_NEXT_ENTRY;
2195                 }
2196                 ace_count++;
2197         }
2198         return ace_count;
2199 }
2200
2201 /****************************************************************************
2202  Utility function to marshall a POSIX acl into wire format.
2203 ****************************************************************************/
2204
2205 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2206 {
2207         int entry_id = SMB_ACL_FIRST_ENTRY;
2208         SMB_ACL_ENTRY_T entry;
2209
2210         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2211                 SMB_ACL_TAG_T tagtype;
2212                 SMB_ACL_PERMSET_T permset;
2213                 unsigned char perms = 0;
2214                 unsigned int own_grp;
2215
2216                 /* get_next... */
2217                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2218                         entry_id = SMB_ACL_NEXT_ENTRY;
2219                 }
2220
2221                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2222                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2223                         return False;
2224                 }
2225
2226                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2227                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2228                         return False;
2229                 }
2230
2231                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2232                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2233                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2234
2235                 SCVAL(pdata,1,perms);
2236
2237                 switch (tagtype) {
2238                         case SMB_ACL_USER_OBJ:
2239                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2240                                 own_grp = (unsigned int)pst->st_uid;
2241                                 SIVAL(pdata,2,own_grp);
2242                                 SIVAL(pdata,6,0);
2243                                 break;
2244                         case SMB_ACL_USER:
2245                                 {
2246                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2247                                         if (!puid) {
2248                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2249                                         }
2250                                         own_grp = (unsigned int)*puid;
2251                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2252                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2253                                         SIVAL(pdata,2,own_grp);
2254                                         SIVAL(pdata,6,0);
2255                                         break;
2256                                 }
2257                         case SMB_ACL_GROUP_OBJ:
2258                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2259                                 own_grp = (unsigned int)pst->st_gid;
2260                                 SIVAL(pdata,2,own_grp);
2261                                 SIVAL(pdata,6,0);
2262                                 break;
2263                         case SMB_ACL_GROUP:
2264                                 {
2265                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2266                                         if (!pgid) {
2267                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2268                                         }
2269                                         own_grp = (unsigned int)*pgid;
2270                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2271                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2272                                         SIVAL(pdata,2,own_grp);
2273                                         SIVAL(pdata,6,0);
2274                                         break;
2275                                 }
2276                         case SMB_ACL_MASK:
2277                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2278                                 SIVAL(pdata,2,0xFFFFFFFF);
2279                                 SIVAL(pdata,6,0xFFFFFFFF);
2280                                 break;
2281                         case SMB_ACL_OTHER:
2282                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2283                                 SIVAL(pdata,2,0xFFFFFFFF);
2284                                 SIVAL(pdata,6,0xFFFFFFFF);
2285                                 break;
2286                         default:
2287                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2288                                 return False;
2289                 }
2290                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2291         }
2292
2293         return True;
2294 }
2295 #endif
2296
2297 /****************************************************************************
2298  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2299  file name or file id).
2300 ****************************************************************************/
2301
2302 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2303                                         char **pparams, int total_params, char **ppdata, int total_data,
2304                                         unsigned int max_data_bytes)
2305 {
2306         char *params = *pparams;
2307         char *pdata = *ppdata;
2308         uint16 tran_call = SVAL(inbuf, smb_setup0);
2309         uint16 info_level;
2310         int mode=0;
2311         SMB_OFF_T file_size=0;
2312         SMB_BIG_UINT allocation_size=0;
2313         unsigned int data_size;
2314         unsigned int param_size = 2;
2315         SMB_STRUCT_STAT sbuf;
2316         pstring fname, dos_fname;
2317         char *fullpathname;
2318         char *base_name;
2319         char *p;
2320         SMB_OFF_T pos = 0;
2321         BOOL bad_path = False;
2322         BOOL delete_pending = False;
2323         int len;
2324         time_t c_time;
2325         files_struct *fsp = NULL;
2326         uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2327
2328         if (!params)
2329                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2330
2331         ZERO_STRUCT(sbuf);
2332
2333         if (tran_call == TRANSACT2_QFILEINFO) {
2334                 if (total_params < 4)
2335                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2336
2337                 fsp = file_fsp(params,0);
2338                 info_level = SVAL(params,2);
2339
2340                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2341
2342                 if(fsp && (fsp->fake_file_handle)) {
2343                         /*
2344                          * This is actually for the QUOTA_FAKE_FILE --metze
2345                          */
2346                                                 
2347                         pstrcpy(fname, fsp->fsp_name);
2348                         /* We know this name is ok, it's already passed the checks. */
2349                         
2350                 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2351                         /*
2352                          * This is actually a QFILEINFO on a directory
2353                          * handle (returned from an NT SMB). NT5.0 seems
2354                          * to do this call. JRA.
2355                          */
2356                         /* We know this name is ok, it's already passed the checks. */
2357                         pstrcpy(fname, fsp->fsp_name);
2358                   
2359                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2360                                 /* Always do lstat for UNIX calls. */
2361                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2362                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2363                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2364                                 }
2365                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2366                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2367                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2368                         }
2369
2370                         delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2371                 } else {
2372                         /*
2373                          * Original code - this is an open file.
2374                          */
2375                         CHECK_FSP(fsp,conn);
2376
2377                         pstrcpy(fname, fsp->fsp_name);
2378                         if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2379                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2380                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2381                         }
2382                         pos = fsp->position_information;
2383                         delete_pending = fsp->delete_on_close;
2384                         desired_access = fsp->desired_access;
2385                 }
2386         } else {
2387                 NTSTATUS status = NT_STATUS_OK;
2388
2389                 /* qpathinfo */
2390                 if (total_params < 6)
2391                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2392
2393                 info_level = SVAL(params,0);
2394
2395                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2396
2397                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2398                 if (!NT_STATUS_IS_OK(status)) {
2399                         return ERROR_NT(status);
2400                 }
2401
2402                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2403
2404                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2405                 if (bad_path) {
2406                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2407                 }
2408                 if (!check_name(fname,conn)) {
2409                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2410                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2411                 }
2412
2413                 if (INFO_LEVEL_IS_UNIX(info_level)) {
2414                         /* Always do lstat for UNIX calls. */
2415                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2416                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2417                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2418                         }
2419                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2420                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2421                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2422                 }
2423         }
2424
2425         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2426                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2427
2428         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2429                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2430
2431         p = strrchr_m(fname,'/'); 
2432         if (!p)
2433                 base_name = fname;
2434         else
2435                 base_name = p+1;
2436
2437         mode = dos_mode(conn,fname,&sbuf);
2438         if (!mode)
2439                 mode = FILE_ATTRIBUTE_NORMAL;
2440
2441         fullpathname = fname;
2442         file_size = get_file_size(sbuf);
2443         allocation_size = get_allocation_size(conn,fsp,&sbuf);
2444         if (mode & aDIR) {
2445                 /* This is necessary, as otherwise the desktop.ini file in
2446                  * this folder is ignored */
2447                 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2448                 file_size = 0;
2449         }
2450
2451         params = SMB_REALLOC(*pparams,2);
2452         if (params == NULL)
2453           return ERROR_DOS(ERRDOS,ERRnomem);
2454         *pparams = params;
2455         memset((char *)params,'\0',2);
2456         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2457         pdata = SMB_REALLOC(*ppdata, data_size); 
2458         if ( pdata == NULL )
2459                 return ERROR_DOS(ERRDOS,ERRnomem);
2460         *ppdata = pdata;
2461
2462         if (total_data > 0 && IVAL(pdata,0) == total_data) {
2463                 /* uggh, EAs for OS2 */
2464                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2465                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2466         }
2467
2468         memset((char *)pdata,'\0',data_size);
2469
2470         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2471
2472         if (fsp) {
2473                 if (fsp->pending_modtime) {
2474                         /* the pending modtime overrides the current modtime */
2475                         sbuf.st_mtime = fsp->pending_modtime;
2476                 }
2477         } else {
2478                 /* Do we have this path open ? */
2479                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2480                 if (fsp1 && fsp1->pending_modtime) {
2481                         /* the pending modtime overrides the current modtime */
2482                         sbuf.st_mtime = fsp1->pending_modtime;
2483                 }
2484         }
2485
2486         if (lp_dos_filetime_resolution(SNUM(conn))) {
2487                 c_time &= ~1;
2488                 sbuf.st_atime &= ~1;
2489                 sbuf.st_ctime &= ~1;
2490                 sbuf.st_mtime &= ~1;
2491         }
2492
2493         /* NT expects the name to be in an exact form of the *full*
2494            filename. See the trans2 torture test */
2495         if (strequal(base_name,".")) {
2496                 pstrcpy(dos_fname, "\\");
2497         } else {
2498                 pstr_sprintf(dos_fname, "\\%s", fname);
2499                 string_replace(dos_fname, '/', '\\');
2500         }
2501
2502         switch (info_level) {
2503                 case SMB_INFO_STANDARD:
2504                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2505                         data_size = 22;
2506                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2507                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2508                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2509                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2510                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2511                         SSVAL(pdata,l1_attrFile,mode);
2512                         break;
2513
2514                 case SMB_INFO_QUERY_EA_SIZE:
2515                 {
2516                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2517                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2518                         data_size = 26;
2519                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2520                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2521                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2522                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2523                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2524                         SSVAL(pdata,l1_attrFile,mode);
2525                         SIVAL(pdata,l1_attrFile+2,ea_size);
2526                         break;
2527                 }
2528
2529                 case SMB_INFO_IS_NAME_VALID:
2530                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2531                         if (tran_call == TRANSACT2_QFILEINFO) {
2532                                 /* os/2 needs this ? really ?*/      
2533                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
2534                         }
2535                         data_size = 0;
2536                         param_size = 0;
2537                         break;
2538                         
2539                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2540                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2541                         data_size = 24;
2542                         put_dos_date2(pdata,0,c_time);
2543                         put_dos_date2(pdata,4,sbuf.st_atime);
2544                         put_dos_date2(pdata,8,sbuf.st_mtime);
2545                         SIVAL(pdata,12,(uint32)file_size);
2546                         SIVAL(pdata,16,(uint32)allocation_size);
2547                         SIVAL(pdata,20,mode);
2548                         break;
2549
2550                 case SMB_INFO_QUERY_ALL_EAS:
2551                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2552                         /* We have data_size bytes to put EA's into. */
2553                         data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2554                         break;
2555
2556                 case SMB_FILE_BASIC_INFORMATION:
2557                 case SMB_QUERY_FILE_BASIC_INFO:
2558
2559                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2560                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2561                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2562                         } else {
2563                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2564                                 data_size = 40;
2565                                 SIVAL(pdata,36,0);
2566                         }
2567                         put_long_date(pdata,c_time);
2568                         put_long_date(pdata+8,sbuf.st_atime);
2569                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2570                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2571                         SIVAL(pdata,32,mode);
2572
2573                         DEBUG(5,("SMB_QFBI - "));
2574                         {
2575                                 time_t create_time = c_time;
2576                                 DEBUG(5,("create: %s ", ctime(&create_time)));
2577                         }
2578                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2579                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2580                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2581                         DEBUG(5,("mode: %x\n", mode));
2582
2583                         break;
2584
2585                 case SMB_FILE_STANDARD_INFORMATION:
2586                 case SMB_QUERY_FILE_STANDARD_INFO:
2587
2588                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2589                         data_size = 24;
2590                         SOFF_T(pdata,0,allocation_size);
2591                         SOFF_T(pdata,8,file_size);
2592                         if (delete_pending & sbuf.st_nlink)
2593                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2594                         else
2595                                 SIVAL(pdata,16,sbuf.st_nlink);
2596                         SCVAL(pdata,20,0);
2597                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2598                         break;
2599
2600                 case SMB_FILE_EA_INFORMATION:
2601                 case SMB_QUERY_FILE_EA_INFO:
2602                 {
2603                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2604                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2605                         data_size = 4;
2606                         SIVAL(pdata,0,ea_size);
2607                         break;
2608                 }
2609
2610                 /* Get the 8.3 name - used if NT SMB was negotiated. */
2611                 case SMB_QUERY_FILE_ALT_NAME_INFO:
2612                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2613                 {
2614                         pstring short_name;
2615
2616                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2617                         pstrcpy(short_name,base_name);
2618                         /* Mangle if not already 8.3 */
2619                         if(!mangle_is_8_3(short_name, True)) {
2620                                 mangle_map(short_name,True,True,SNUM(conn));
2621                         }
2622                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2623                         data_size = 4 + len;
2624                         SIVAL(pdata,0,len);
2625                         break;
2626                 }
2627
2628                 case SMB_QUERY_FILE_NAME_INFO:
2629                         /*
2630                           this must be *exactly* right for ACLs on mapped drives to work
2631                          */
2632                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2633                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2634                         data_size = 4 + len;
2635                         SIVAL(pdata,0,len);
2636                         break;
2637
2638                 case SMB_FILE_ALLOCATION_INFORMATION:
2639                 case SMB_QUERY_FILE_ALLOCATION_INFO:
2640                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2641                         data_size = 8;
2642                         SOFF_T(pdata,0,allocation_size);
2643                         break;
2644
2645                 case SMB_FILE_END_OF_FILE_INFORMATION:
2646                 case SMB_QUERY_FILE_END_OF_FILEINFO:
2647                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2648                         data_size = 8;
2649                         SOFF_T(pdata,0,file_size);
2650                         break;
2651
2652                 case SMB_QUERY_FILE_ALL_INFO:
2653                 case SMB_FILE_ALL_INFORMATION:
2654                 {
2655                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2656                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2657                         put_long_date(pdata,c_time);
2658                         put_long_date(pdata+8,sbuf.st_atime);
2659                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2660                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2661                         SIVAL(pdata,32,mode);
2662                         pdata += 40;
2663                         SOFF_T(pdata,0,allocation_size);
2664                         SOFF_T(pdata,8,file_size);
2665                         if (delete_pending && sbuf.st_nlink)
2666                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2667                         else
2668                                 SIVAL(pdata,16,sbuf.st_nlink);
2669                         SCVAL(pdata,20,delete_pending);
2670                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2671                         pdata += 24;
2672                         SIVAL(pdata,0,ea_size);
2673                         pdata += 4; /* EA info */
2674                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2675                         SIVAL(pdata,0,len);
2676                         pdata += 4 + len;
2677                         data_size = PTR_DIFF(pdata,(*ppdata));
2678                         break;
2679                 }
2680                 case SMB_FILE_INTERNAL_INFORMATION:
2681                         /* This should be an index number - looks like
2682                            dev/ino to me :-) 
2683
2684                            I think this causes us to fail the IFSKIT
2685                            BasicFileInformationTest. -tpot */
2686
2687                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2688                         SIVAL(pdata,0,sbuf.st_dev);
2689                         SIVAL(pdata,4,sbuf.st_ino);
2690                         data_size = 8;
2691                         break;
2692
2693                 case SMB_FILE_ACCESS_INFORMATION:
2694                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2695                         SIVAL(pdata,0,desired_access);
2696                         data_size = 4;
2697                         break;
2698
2699                 case SMB_FILE_NAME_INFORMATION:
2700                         /* Pathname with leading '\'. */
2701                         {
2702                                 size_t byte_len;
2703                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2704                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2705                                 SIVAL(pdata,0,byte_len);
2706                                 data_size = 4 + byte_len;
2707                                 break;
2708                         }
2709
2710                 case SMB_FILE_DISPOSITION_INFORMATION:
2711                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2712                         data_size = 1;
2713                         SCVAL(pdata,0,delete_pending);
2714                         break;
2715
2716                 case SMB_FILE_POSITION_INFORMATION:
2717                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2718                         data_size = 8;
2719                         SOFF_T(pdata,0,pos);
2720                         break;
2721
2722                 case SMB_FILE_MODE_INFORMATION:
2723                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2724                         SIVAL(pdata,0,mode);
2725                         data_size = 4;
2726                         break;
2727
2728                 case SMB_FILE_ALIGNMENT_INFORMATION:
2729                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2730                         SIVAL(pdata,0,0); /* No alignment needed. */
2731                         data_size = 4;
2732                         break;
2733
2734 #if 0
2735                 /*
2736                  * NT4 server just returns "invalid query" to this - if we try to answer
2737                  * it then NTws gets a BSOD! (tridge).
2738                  * W2K seems to want this. JRA.
2739                  */
2740                 case SMB_QUERY_FILE_STREAM_INFO:
2741 #endif
2742                 case SMB_FILE_STREAM_INFORMATION:
2743                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2744                         if (mode & aDIR) {
2745                                 data_size = 0;
2746                         } else {
2747                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2748                                 SIVAL(pdata,0,0); /* ??? */
2749                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2750                                 SOFF_T(pdata,8,file_size);
2751                                 SIVAL(pdata,16,allocation_size);
2752                                 SIVAL(pdata,20,0); /* ??? */
2753                                 data_size = 24 + byte_len;
2754                         }
2755                         break;
2756
2757                 case SMB_QUERY_COMPRESSION_INFO:
2758                 case SMB_FILE_COMPRESSION_INFORMATION:
2759                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2760                         SOFF_T(pdata,0,file_size);
2761                         SIVAL(pdata,8,0); /* ??? */
2762                         SIVAL(pdata,12,0); /* ??? */
2763                         data_size = 16;
2764                         break;
2765
2766                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2767                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2768                         put_long_date(pdata,c_time);
2769                         put_long_date(pdata+8,sbuf.st_atime);
2770                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2771                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2772                         SIVAL(pdata,32,allocation_size);
2773                         SOFF_T(pdata,40,file_size);
2774                         SIVAL(pdata,48,mode);
2775                         SIVAL(pdata,52,0); /* ??? */
2776                         data_size = 56;
2777                         break;
2778
2779                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2780                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2781                         SIVAL(pdata,0,mode);
2782                         SIVAL(pdata,4,0);
2783                         data_size = 8;
2784                         break;
2785
2786                 /*
2787                  * CIFS UNIX Extensions.
2788                  */
2789
2790                 case SMB_QUERY_FILE_UNIX_BASIC:
2791
2792                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2793                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2794
2795                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
2796                         pdata += 8;
2797
2798                         SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2799                         pdata += 8;
2800
2801                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
2802                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
2803                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
2804                         pdata += 24;
2805
2806                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
2807                         SIVAL(pdata,4,0);
2808                         pdata += 8;
2809
2810                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
2811                         SIVAL(pdata,4,0);
2812                         pdata += 8;
2813
2814                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2815                         pdata += 4;
2816
2817                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
2818                         SIVAL(pdata,4,0);
2819                         pdata += 8;
2820
2821                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
2822                         SIVAL(pdata,4,0);
2823                         pdata += 8;
2824
2825                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
2826                         pdata += 8;
2827                                 
2828                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
2829                         SIVAL(pdata,4,0);
2830                         pdata += 8;
2831
2832                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
2833                         SIVAL(pdata,4,0);
2834                         pdata += 8+1;
2835                         data_size = PTR_DIFF(pdata,(*ppdata));
2836
2837                         {
2838                                 int i;
2839                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2840
2841                                 for (i=0; i<100; i++)
2842                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2843                                 DEBUG(4,("\n"));
2844                         }
2845
2846                         break;
2847
2848                 case SMB_QUERY_FILE_UNIX_LINK:
2849                         {
2850                                 pstring buffer;
2851
2852                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2853 #ifdef S_ISLNK
2854                                 if(!S_ISLNK(sbuf.st_mode))
2855                                         return(UNIXERROR(ERRSRV,ERRbadlink));
2856 #else
2857                                 return(UNIXERROR(ERRDOS,ERRbadlink));
2858 #endif
2859                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
2860                                 if (len == -1)
2861                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2862                                 buffer[len] = 0;
2863                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2864                                 pdata += len;
2865                                 data_size = PTR_DIFF(pdata,(*ppdata));
2866
2867                                 break;
2868                         }
2869
2870 #if defined(HAVE_POSIX_ACLS)
2871                 case SMB_QUERY_POSIX_ACL:
2872                         {
2873                                 SMB_ACL_T file_acl = NULL;
2874                                 SMB_ACL_T def_acl = NULL;
2875                                 uint16 num_file_acls = 0;
2876                                 uint16 num_def_acls = 0;
2877
2878                                 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
2879                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
2880                                 } else {
2881                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
2882                                 }
2883
2884                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2885                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
2886                                                 fname ));
2887                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
2888                                 }
2889
2890                                 if (S_ISDIR(sbuf.st_mode)) {
2891                                         if (fsp && fsp->is_directory) {
2892                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
2893                                         } else {
2894                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
2895                                         }
2896                                         def_acl = free_empty_sys_acl(conn, def_acl);
2897                                 }
2898
2899                                 num_file_acls = count_acl_entries(conn, file_acl);
2900                                 num_def_acls = count_acl_entries(conn, def_acl);
2901
2902                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
2903                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
2904                                                 data_size,
2905                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
2906                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
2907                                         if (file_acl) {
2908                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2909                                         }
2910                                         if (def_acl) {
2911                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2912                                         }
2913                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2914                                 }
2915
2916                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2917                                 SSVAL(pdata,2,num_file_acls);
2918                                 SSVAL(pdata,4,num_def_acls);
2919                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
2920                                         if (file_acl) {
2921                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2922                                         }
2923                                         if (def_acl) {
2924                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2925                                         }
2926                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2927                                 }
2928                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
2929                                         if (file_acl) {
2930                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2931                                         }
2932                                         if (def_acl) {
2933                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2934                                         }
2935                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2936                                 }
2937
2938                                 if (file_acl) {
2939                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2940                                 }
2941                                 if (def_acl) {
2942                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2943                                 }
2944                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
2945                                 break;
2946                         }
2947 #endif
2948
2949                 default:
2950                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2951         }
2952
2953         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2954
2955         return(-1);
2956 }
2957
2958 /****************************************************************************
2959  Deal with the internal needs of setting the delete on close flag. Note that
2960  as the tdb locking is recursive, it is safe to call this from within 
2961  open_file_shared. JRA.
2962 ****************************************************************************/
2963
2964 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
2965 {
2966         if (delete_on_close) {
2967                 /*
2968                  * Only allow delete on close for writable files.
2969                  */
2970
2971                 if (!lp_delete_readonly(SNUM(fsp->conn))) {
2972                         if (dosmode & aRONLY) {
2973                                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
2974                                         fsp->fsp_name ));
2975                                 return NT_STATUS_CANNOT_DELETE;
2976                         }
2977                 }
2978
2979                 /*
2980                  * Only allow delete on close for writable shares.
2981                  */
2982
2983                 if (!CAN_WRITE(fsp->conn)) {
2984                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2985                                 fsp->fsp_name ));
2986                         return NT_STATUS_ACCESS_DENIED;
2987                 }
2988
2989                 /*
2990                  * Only allow delete on close for files/directories opened with delete intent.
2991                  */
2992
2993                 if (!(fsp->desired_access & DELETE_ACCESS)) {
2994                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2995                                 fsp->fsp_name ));
2996                         return NT_STATUS_ACCESS_DENIED;
2997                 }
2998         }
2999
3000         if(fsp->is_directory) {
3001                 fsp->directory_delete_on_close = delete_on_close;
3002                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3003                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3004         } else {
3005                 fsp->delete_on_close = delete_on_close;
3006                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3007                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3008         }
3009
3010         return NT_STATUS_OK;
3011 }
3012
3013 /****************************************************************************
3014  Sets the delete on close flag over all share modes on this file.
3015  Modify the share mode entry for all files open
3016  on this device and inode to tell other smbds we have
3017  changed the delete on close flag. This will be noticed
3018  in the close code, the last closer will delete the file
3019  if flag is set.
3020 ****************************************************************************/
3021
3022 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3023 {
3024         DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3025                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3026
3027         if (fsp->is_directory || fsp->is_stat)
3028                 return NT_STATUS_OK;
3029
3030         if (lock_share_entry_fsp(fsp) == False)
3031                 return NT_STATUS_ACCESS_DENIED;
3032
3033         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3034                 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3035                         fsp->fsp_name ));
3036                 unlock_share_entry_fsp(fsp);
3037                 return NT_STATUS_ACCESS_DENIED;
3038         }
3039
3040         unlock_share_entry_fsp(fsp);
3041         return NT_STATUS_OK;
3042 }
3043
3044 /****************************************************************************
3045  Set a hard link (called by UNIX extensions and by NT rename with HARD link
3046  code.
3047 ****************************************************************************/
3048
3049 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3050 {
3051         BOOL bad_path_oldname = False;
3052         BOOL bad_path_newname = False;
3053         SMB_STRUCT_STAT sbuf1, sbuf2;
3054         pstring last_component_oldname;
3055         pstring last_component_newname;
3056         NTSTATUS status = NT_STATUS_OK;
3057
3058         ZERO_STRUCT(sbuf1);
3059         ZERO_STRUCT(sbuf2);
3060
3061         /* No wildcards. */
3062         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3063                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3064         }
3065
3066         unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3067         if (bad_path_oldname) {
3068                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3069         }
3070
3071         /* Quick check for "." and ".." */
3072         if (last_component_oldname[0] == '.') {
3073                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3074                         return NT_STATUS_OBJECT_NAME_INVALID;
3075                 }
3076         }
3077
3078         /* source must already exist. */
3079         if (!VALID_STAT(sbuf1)) {
3080                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3081         }
3082
3083         if (!check_name(oldname,conn)) {
3084                 return NT_STATUS_ACCESS_DENIED;
3085         }
3086
3087         unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3088         if (bad_path_newname) {
3089                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3090         }
3091
3092         /* Quick check for "." and ".." */
3093         if (last_component_newname[0] == '.') {
3094                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3095                         return NT_STATUS_OBJECT_NAME_INVALID;
3096                 }
3097         }
3098
3099         /* Disallow if newname already exists. */
3100         if (VALID_STAT(sbuf2)) {
3101                 return NT_STATUS_OBJECT_NAME_COLLISION;
3102         }
3103
3104         if (!check_name(newname,conn)) {
3105                 return NT_STATUS_ACCESS_DENIED;
3106         }
3107
3108         /* No links from a directory. */
3109         if (S_ISDIR(sbuf1.st_mode)) {
3110                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3111         }
3112
3113         /* Ensure this is within the share. */
3114         if (!reduce_name(conn, oldname) != 0)
3115                 return NT_STATUS_ACCESS_DENIED;
3116
3117         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3118
3119         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3120                 status = map_nt_error_from_unix(errno);
3121                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3122                                 nt_errstr(status), newname, oldname));
3123         }
3124
3125         return status;
3126 }
3127
3128 /****************************************************************************
3129  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3130 ****************************************************************************/
3131
3132 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3133                                         char **pparams, int total_params, char **ppdata, int total_data,
3134                                         unsigned int max_data_bytes)
3135 {
3136         char *params = *pparams;
3137         char *pdata = *ppdata;
3138         uint16 tran_call = SVAL(inbuf, smb_setup0);
3139         uint16 info_level;
3140         int dosmode=0;
3141         SMB_OFF_T size=0;
3142         struct utimbuf tvs;
3143         SMB_STRUCT_STAT sbuf;
3144         pstring fname;
3145         int fd = -1;
3146         BOOL bad_path = False;
3147         files_struct *fsp = NULL;
3148         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3149         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3150         mode_t unixmode = 0;
3151         NTSTATUS status = NT_STATUS_OK;
3152
3153         if (!params)
3154                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3155
3156         ZERO_STRUCT(sbuf);
3157
3158         if (tran_call == TRANSACT2_SETFILEINFO) {
3159                 if (total_params < 4)
3160                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3161
3162                 fsp = file_fsp(params,0);
3163                 info_level = SVAL(params,2);    
3164
3165                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3166                         /*
3167                          * This is actually a SETFILEINFO on a directory
3168                          * handle (returned from an NT SMB). NT5.0 seems
3169                          * to do this call. JRA.
3170                          */
3171                         pstrcpy(fname, fsp->fsp_name);
3172                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3173                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3174                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3175                         }
3176                 } else if (fsp && fsp->print_file) {
3177                         /*
3178                          * Doing a DELETE_ON_CLOSE should cancel a print job.
3179                          */
3180                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3181                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3182
3183                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3184         
3185                                 SSVAL(params,0,0);
3186                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3187                                 return(-1);
3188                         } else
3189                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3190             } else {
3191                         /*
3192                          * Original code - this is an open file.
3193                          */
3194                         CHECK_FSP(fsp,conn);
3195
3196                         pstrcpy(fname, fsp->fsp_name);
3197                         fd = fsp->fd;
3198
3199                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3200                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3201                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3202                         }
3203                 }
3204         } else {
3205                 /* set path info */
3206                 if (total_params < 6)
3207                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3208
3209                 info_level = SVAL(params,0);    
3210                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3211                 if (!NT_STATUS_IS_OK(status)) {
3212                         return ERROR_NT(status);
3213                 }
3214                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3215                 if (bad_path) {
3216                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3217                 }
3218
3219                 /*
3220                  * For CIFS UNIX extensions the target name may not exist.
3221                  */
3222
3223                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3224                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3225                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3226                 }    
3227
3228                 if(!check_name(fname, conn)) {
3229                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3230                 }
3231
3232         }
3233
3234         if (!CAN_WRITE(conn))
3235                 return ERROR_DOS(ERRSRV,ERRaccess);
3236
3237         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3238                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3239
3240         if (VALID_STAT(sbuf))
3241                 unixmode = sbuf.st_mode;
3242
3243         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3244                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3245
3246         /* Realloc the parameter and data sizes */
3247         params = SMB_REALLOC(*pparams,2);
3248         if(params == NULL)
3249                 return ERROR_DOS(ERRDOS,ERRnomem);
3250         *pparams = params;
3251
3252         SSVAL(params,0,0);
3253
3254         if (fsp && fsp->pending_modtime) {
3255                 /* the pending modtime overrides the current modtime */
3256                 sbuf.st_mtime = fsp->pending_modtime;
3257         }
3258
3259         size = get_file_size(sbuf);
3260         tvs.modtime = sbuf.st_mtime;
3261         tvs.actime = sbuf.st_atime;
3262         dosmode = dos_mode(conn,fname,&sbuf);
3263         unixmode = sbuf.st_mode;
3264
3265         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3266         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3267
3268         switch (info_level) {
3269                 case SMB_INFO_STANDARD:
3270                 {
3271                         if (total_data < 12)
3272                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3273
3274                         /* access time */
3275                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3276                         /* write time */
3277                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3278                         break;
3279                 }
3280
3281                 case SMB_INFO_SET_EA:
3282                         status = set_ea(conn, fsp, fname, pdata, total_data);
3283                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3284                                 return ERROR_NT(status);
3285                         break;
3286
3287                 /* XXXX um, i don't think this is right.
3288                         it's also not in the cifs6.txt spec.
3289                 */
3290                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3291                         if (total_data < 28)
3292                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3293
3294                         tvs.actime = make_unix_date2(pdata+8);
3295                         tvs.modtime = make_unix_date2(pdata+12);
3296                         size = IVAL(pdata,16);
3297                         dosmode = IVAL(pdata,24);
3298                         break;
3299
3300                 /* XXXX nor this.  not in cifs6.txt, either. */
3301                 case SMB_INFO_QUERY_ALL_EAS:
3302                         if (total_data < 28)
3303                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3304
3305                         tvs.actime = make_unix_date2(pdata+8);
3306                         tvs.modtime = make_unix_date2(pdata+12);
3307                         size = IVAL(pdata,16);
3308                         dosmode = IVAL(pdata,24);
3309                         break;
3310
3311                 case SMB_SET_FILE_BASIC_INFO:
3312                 case SMB_FILE_BASIC_INFORMATION:
3313                 {
3314                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3315                         time_t write_time;
3316                         time_t changed_time;
3317
3318                         if (total_data < 36)
3319                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3320
3321                         /* Ignore create time at offset pdata. */
3322
3323                         /* access time */
3324                         tvs.actime = interpret_long_date(pdata+8);
3325
3326                         write_time = interpret_long_date(pdata+16);
3327                         changed_time = interpret_long_date(pdata+24);
3328
3329                         tvs.modtime = MIN(write_time, changed_time);
3330
3331                         if (write_time > tvs.modtime && write_time != (time_t)-1) {
3332                                 tvs.modtime = write_time;
3333                         }
3334                         /* Prefer a defined time to an undefined one. */
3335                         if (null_mtime(tvs.modtime)) {
3336                                 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3337                         }
3338
3339                         /* attributes */
3340                         dosmode = IVAL(pdata,32);
3341                         break;
3342                 }
3343
3344                 case SMB_FILE_ALLOCATION_INFORMATION:
3345                 case SMB_SET_FILE_ALLOCATION_INFO:
3346                 {
3347                         int ret = -1;
3348                         SMB_BIG_UINT allocation_size;
3349
3350                         if (total_data < 8)
3351                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3352
3353                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3354 #ifdef LARGE_SMB_OFF_T
3355                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3356 #else /* LARGE_SMB_OFF_T */
3357                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3358                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3359 #endif /* LARGE_SMB_OFF_T */
3360                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3361                                         fname, (double)allocation_size ));
3362
3363                         if (allocation_size) {
3364                                 allocation_size = smb_roundup(conn, allocation_size);
3365                         }
3366
3367                         if(allocation_size != get_file_size(sbuf)) {
3368                                 SMB_STRUCT_STAT new_sbuf;
3369  
3370                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3371                                         fname, (double)allocation_size ));
3372  
3373                                 if (fd == -1) {
3374                                         files_struct *new_fsp = NULL;
3375                                         int access_mode = 0;
3376                                         int action = 0;
3377  
3378                                         if(global_oplock_break) {
3379                                                 /* Queue this file modify as we are the process of an oplock break.  */
3380  
3381                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3382                                                 DEBUGADD(2,( "in oplock break state.\n"));
3383  
3384                                                 push_oplock_pending_smb_message(inbuf, length);
3385                                                 return -1;
3386                                         }
3387  
3388                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3389                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
3390                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3391                                                                         FILE_ATTRIBUTE_NORMAL,
3392                                                                         INTERNAL_OPEN_ONLY, &access_mode, &action);
3393  
3394                                         if (new_fsp == NULL)
3395                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3396                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
3397                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3398                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3399                                                                         new_fsp->fnum, strerror(errno)));
3400                                                 ret = -1;
3401                                         }
3402                                         close_file(new_fsp,True);
3403                                 } else {
3404                                         ret = vfs_allocate_file_space(fsp, allocation_size);
3405                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3406                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3407                                                                         fsp->fnum, strerror(errno)));
3408                                                 ret = -1;
3409                                         }
3410                                 }
3411                                 if (ret == -1)
3412                                         return ERROR_NT(NT_STATUS_DISK_FULL);
3413
3414                                 /* Allocate can truncate size... */
3415                                 size = get_file_size(new_sbuf);
3416                         }
3417
3418                         break;
3419                 }
3420
3421                 case SMB_FILE_END_OF_FILE_INFORMATION:
3422                 case SMB_SET_FILE_END_OF_FILE_INFO:
3423                 {
3424                         if (total_data < 8)
3425                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3426
3427                         size = IVAL(pdata,0);
3428 #ifdef LARGE_SMB_OFF_T
3429                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3430 #else /* LARGE_SMB_OFF_T */
3431                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3432                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3433 #endif /* LARGE_SMB_OFF_T */
3434                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3435                         break;
3436                 }
3437
3438                 case SMB_FILE_DISPOSITION_INFORMATION:
3439                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3440                 {
3441                         BOOL delete_on_close;
3442
3443                         if (total_data < 1)
3444                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3445
3446                         delete_on_close = (CVAL(pdata,0) ? True : False);
3447
3448                         /* Just ignore this set on a path. */
3449                         if (tran_call != TRANSACT2_SETFILEINFO)
3450                                 break;
3451
3452                         if (fsp == NULL)
3453                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3454
3455                         status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3456  
3457                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3458                                 return ERROR_NT(status);
3459
3460                         /* The set is across all open files on this dev/inode pair. */
3461                         status =set_delete_on_close_over_all(fsp, delete_on_close);
3462                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3463                                 return ERROR_NT(status);
3464
3465                         break;
3466                 }
3467
3468                 case SMB_FILE_POSITION_INFORMATION:
3469                 {
3470                         SMB_BIG_UINT position_information;
3471
3472                         if (total_data < 8)
3473                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3474
3475                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3476 #ifdef LARGE_SMB_OFF_T
3477                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3478 #else /* LARGE_SMB_OFF_T */
3479                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3480                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3481 #endif /* LARGE_SMB_OFF_T */
3482                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3483                                         fname, (double)position_information ));
3484                         if (fsp)
3485                                 fsp->position_information = position_information;
3486                         break;
3487                 }
3488
3489                 /*
3490                  * CIFS UNIX extensions.
3491                  */
3492
3493                 case SMB_SET_FILE_UNIX_BASIC:
3494                 {
3495                         uint32 raw_unixmode;
3496
3497                         if (total_data < 100)
3498                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3499
3500                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3501                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3502                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
3503 #ifdef LARGE_SMB_OFF_T
3504                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3505 #else /* LARGE_SMB_OFF_T */
3506                                 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3507                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3508 #endif /* LARGE_SMB_OFF_T */
3509                         }
3510                         pdata+=24;          /* ctime & st_blocks are not changed */
3511                         tvs.actime = interpret_long_date(pdata); /* access_time */
3512                         tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3513                         pdata+=16;
3514                         set_owner = (uid_t)IVAL(pdata,0);
3515                         pdata += 8;
3516                         set_grp = (gid_t)IVAL(pdata,0);
3517                         pdata += 8;
3518                         raw_unixmode = IVAL(pdata,28);
3519                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3520                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
3521
3522                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3523 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3524                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3525
3526                         if (!VALID_STAT(sbuf)) {
3527
3528                                 /*
3529                                  * The only valid use of this is to create character and block
3530                                  * devices, and named pipes. This is deprecated (IMHO) and 
3531                                  * a new info level should be used for mknod. JRA.
3532                                  */
3533
3534                                 uint32 file_type = IVAL(pdata,0);
3535 #if defined(HAVE_MAKEDEV)
3536                                 uint32 dev_major = IVAL(pdata,4);
3537                                 uint32 dev_minor = IVAL(pdata,12);
3538 #endif
3539
3540                                 uid_t myuid = geteuid();
3541                                 gid_t mygid = getegid();
3542                                 SMB_DEV_T dev = (SMB_DEV_T)0;
3543
3544                                 if (tran_call == TRANSACT2_SETFILEINFO)
3545                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3546
3547                                 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3548                                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3549
3550 #if defined(HAVE_MAKEDEV)
3551                                 dev = makedev(dev_major, dev_minor);
3552 #endif
3553
3554                                 /* We can only create as the owner/group we are. */
3555
3556                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3557                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3558                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3559                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3560
3561                                 switch (file_type) {
3562 #if defined(S_IFIFO)
3563                                         case UNIX_TYPE_FIFO:
3564                                                 unixmode |= S_IFIFO;
3565                                                 break;
3566 #endif
3567 #if defined(S_IFSOCK)
3568                                         case UNIX_TYPE_SOCKET:
3569                                                 unixmode |= S_IFSOCK;
3570                                                 break;
3571 #endif
3572 #if defined(S_IFCHR)
3573                                         case UNIX_TYPE_CHARDEV:
3574                                                 unixmode |= S_IFCHR;
3575                                                 break;
3576 #endif
3577 #if defined(S_IFBLK)
3578                                         case UNIX_TYPE_BLKDEV:
3579                                                 unixmode |= S_IFBLK;
3580                                                 break;
3581 #endif
3582                                         default:
3583                                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3584                                 }
3585
3586                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3587 0%o for file %s\n", (double)dev, unixmode, fname ));
3588
3589                                 /* Ok - do the mknod. */
3590                                 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3591                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3592
3593                                 inherit_access_acl(conn, fname, unixmode);
3594
3595                                 SSVAL(params,0,0);
3596                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3597                                 return(-1);
3598                         }
3599
3600                         /*
3601                          * Deal with the UNIX specific mode set.
3602                          */
3603
3604                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3605                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3606                                         (unsigned int)unixmode, fname ));
3607                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3608                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3609                         }
3610
3611                         /*
3612                          * Deal with the UNIX specific uid set.
3613                          */
3614
3615                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3616                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3617                                         (unsigned int)set_owner, fname ));
3618                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3619                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3620                         }
3621
3622                         /*
3623                          * Deal with the UNIX specific gid set.
3624                          */
3625
3626                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3627                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3628                                         (unsigned int)set_owner, fname ));
3629                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3630                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3631                         }
3632                         break;
3633                 }
3634
3635                 case SMB_SET_FILE_UNIX_LINK:
3636                 {
3637                         pstring link_target;
3638                         char *newname = fname;
3639
3640                         /* Set a symbolic link. */
3641                         /* Don't allow this if follow links is false. */
3642
3643                         if (!lp_symlinks(SNUM(conn)))
3644                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3645
3646                         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3647
3648                         /* !widelinks forces the target path to be within the share. */
3649                         /* This means we can interpret the target as a pathname. */
3650                         if (!lp_widelinks(SNUM(conn))) {
3651                                 pstring rel_name;
3652                                 char *last_dirp = NULL;
3653
3654                                 unix_format(link_target);
3655                                 if (*link_target == '/') {
3656                                         /* No absolute paths allowed. */
3657                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3658                                 }
3659                                 pstrcpy(rel_name, newname);
3660                                 last_dirp = strrchr_m(rel_name, '/');
3661                                 if (last_dirp) {
3662                                         last_dirp[1] = '\0';
3663                                 } else {
3664                                         pstrcpy(rel_name, "./");
3665                                 }
3666                                 pstrcat(rel_name, link_target);
3667
3668                                 if (!check_name(rel_name, conn)) {
3669                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3670                                 }
3671                         }
3672
3673                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3674                                 fname, link_target ));
3675
3676                         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3677                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3678                         SSVAL(params,0,0);
3679                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3680                         return(-1);
3681                 }
3682
3683                 case SMB_SET_FILE_UNIX_HLINK:
3684                 {
3685                         pstring oldname;
3686                         char *newname = fname;
3687
3688                         /* Set a hard link. */
3689                         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3690                         if (!NT_STATUS_IS_OK(status)) {
3691                                 return ERROR_NT(status);
3692                         }
3693
3694                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3695                                 fname, oldname));
3696
3697                         status = hardlink_internals(conn, oldname, newname);
3698                         if (!NT_STATUS_IS_OK(status)) {
3699                                 return ERROR_NT(status);
3700                         }
3701
3702                         SSVAL(params,0,0);
3703                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3704                         return(-1);
3705                 }
3706
3707                 case SMB_FILE_RENAME_INFORMATION:
3708                 {
3709                         BOOL overwrite;
3710                         uint32 root_fid;
3711                         uint32 len;
3712                         pstring newname;
3713                         pstring base_name;
3714                         char *p;
3715
3716                         if (total_data < 12)
3717                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3718
3719                         overwrite = (CVAL(pdata,0) ? True : False);
3720                         root_fid = IVAL(pdata,4);
3721                         len = IVAL(pdata,8);
3722                         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3723                         if (!NT_STATUS_IS_OK(status)) {
3724                                 return ERROR_NT(status);
3725                         }
3726
3727                         /* Check the new name has no '/' characters. */
3728                         if (strchr_m(newname, '/'))
3729                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3730
3731                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3732
3733                         /* Create the base directory. */
3734                         pstrcpy(base_name, fname);
3735                         p = strrchr_m(base_name, '/');
3736                         if (p)
3737                                 *p = '\0';
3738                         /* Append the new name. */
3739                         pstrcat(base_name, "/");
3740                         pstrcat(base_name, newname);
3741
3742                         if (fsp) {
3743                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3744                                         fsp->fnum, fsp->fsp_name, base_name ));
3745                                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3746                         } else {
3747                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3748                                         fname, newname ));
3749                                 status = rename_internals(conn, fname, base_name, 0, overwrite);
3750                         }
3751                         if (!NT_STATUS_IS_OK(status)) {
3752                                 return ERROR_NT(status);
3753                         }
3754                         process_pending_change_notify_queue((time_t)0);
3755                         SSVAL(params,0,0);
3756                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3757                         return(-1);
3758                 }
3759
3760 #if defined(HAVE_POSIX_ACLS)
3761                 case SMB_SET_POSIX_ACL:
3762                 {
3763                         uint16 posix_acl_version;
3764                         uint16 num_file_acls;
3765                         uint16 num_def_acls;
3766                         BOOL valid_file_acls = True;
3767                         BOOL valid_def_acls = True;
3768
3769                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3770                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3771                         }
3772                         posix_acl_version = SVAL(pdata,0);
3773                         num_file_acls = SVAL(pdata,2);
3774                         num_def_acls = SVAL(pdata,4);
3775
3776                         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3777                                 valid_file_acls = False;
3778                                 num_file_acls = 0;
3779                         }
3780
3781                         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3782                                 valid_def_acls = False;
3783                                 num_def_acls = 0;
3784                         }
3785
3786                         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3787                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3788                         }
3789
3790                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3791                                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3792                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3793                         }
3794
3795                         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3796                                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3797                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3798                         }
3799
3800                         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3801                                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
3802                                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3803                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3804                         }
3805
3806                         SSVAL(params,0,0);
3807                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3808                         return(-1);
3809                 }
3810 #endif
3811
3812                 default:
3813                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3814         }
3815
3816         /* get some defaults (no modifications) if any info is zero or -1. */
3817         if (null_mtime(tvs.actime)) {
3818                 tvs.actime = sbuf.st_atime;
3819         }
3820
3821         if (null_mtime(tvs.modtime)) {
3822                 tvs.modtime = sbuf.st_mtime;
3823         }
3824
3825         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3826         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3827         DEBUG(6,("size: %.0f ", (double)size));
3828
3829         if (dosmode) {
3830                 if (S_ISDIR(sbuf.st_mode))
3831                         dosmode |= aDIR;
3832                 else
3833                         dosmode &= ~aDIR;
3834         }
3835
3836         DEBUG(6,("dosmode: %x\n"  , dosmode));
3837
3838         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3839                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3840                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3841                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3842
3843                 /*
3844                  * Only do this test if we are not explicitly
3845                  * changing the size of a file.
3846                  */
3847                 if (!size)
3848                         size = get_file_size(sbuf);
3849         }
3850
3851         /*
3852          * Try and set the times, size and mode of this file -
3853          * if they are different from the current values
3854          */
3855
3856         /* check the mode isn't different, before changing it */
3857         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3858
3859                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3860
3861                 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
3862                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3863                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3864                 }
3865         }
3866
3867         /* Now the size. */
3868         if (size != get_file_size(sbuf)) {
3869
3870                 int ret;
3871
3872                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3873                         fname, (double)size ));
3874
3875                 if (fd == -1) {
3876                         files_struct *new_fsp = NULL;
3877                         int access_mode = 0;
3878                         int action = 0;
3879
3880                         if(global_oplock_break) {
3881                                 /* Queue this file modify as we are the process of an oplock break.  */
3882
3883                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3884                                 DEBUGADD(2,( "in oplock break state.\n"));
3885
3886                                 push_oplock_pending_smb_message(inbuf, length);
3887                                 return -1;
3888                         }
3889
3890                         new_fsp = open_file_shared(conn, fname, &sbuf,
3891                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
3892                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3893                                                 FILE_ATTRIBUTE_NORMAL,
3894                                                 INTERNAL_OPEN_ONLY, &access_mode, &action);
3895         
3896                         if (new_fsp == NULL)
3897                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3898                         ret = vfs_set_filelen(new_fsp, size);
3899                         close_file(new_fsp,True);
3900                 } else {
3901                         ret = vfs_set_filelen(fsp, size);
3902                 }
3903
3904                 if (ret == -1)
3905                         return (UNIXERROR(ERRHRD,ERRdiskfull));
3906         }
3907
3908         /*
3909          * Finally the times.
3910          */
3911         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3912                 if(fsp != NULL) {
3913                         /*
3914                          * This was a setfileinfo on an open file.
3915                          * NT does this a lot. We also need to 
3916                          * set the time here, as it can be read by 
3917                          * FindFirst/FindNext and with the patch for bug #2045
3918                          * in smbd/fileio.c it ensures that this timestamp is
3919                          * kept sticky even after a write. We save the request
3920                          * away and will set it on file close and after a write. JRA.
3921                          */
3922
3923                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3924                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3925                                 fsp_set_pending_modtime(fsp, tvs.modtime);
3926                         }
3927
3928                 }
3929                 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3930
3931                 if(file_utime(conn, fname, &tvs)!=0) {
3932                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3933                 }
3934         }
3935
3936         SSVAL(params,0,0);
3937         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3938   
3939         return(-1);
3940 }
3941
3942 /****************************************************************************
3943  Reply to a TRANS2_MKDIR (make directory with extended attributes).
3944 ****************************************************************************/
3945
3946 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3947                                         char **pparams, int total_params, char **ppdata, int total_data,
3948                                         unsigned int max_data_bytes)
3949 {
3950         char *params = *pparams;
3951         pstring directory;
3952         int ret = -1;
3953         SMB_STRUCT_STAT sbuf;
3954         BOOL bad_path = False;
3955         NTSTATUS status = NT_STATUS_OK;
3956
3957         if (!CAN_WRITE(conn))
3958                 return ERROR_DOS(ERRSRV,ERRaccess);
3959
3960         if (total_params < 4)
3961                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3962
3963         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
3964         if (!NT_STATUS_IS_OK(status)) {
3965                 return ERROR_NT(status);
3966         }
3967
3968         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3969
3970         unix_convert(directory,conn,0,&bad_path,&sbuf);
3971         if (bad_path) {
3972                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3973         }
3974         if (check_name(directory,conn))
3975                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3976   
3977         if(ret < 0) {
3978                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3979                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3980         }
3981
3982         /* Realloc the parameter and data sizes */
3983         params = SMB_REALLOC(*pparams,2);
3984         if(params == NULL)
3985                 return ERROR_DOS(ERRDOS,ERRnomem);
3986         *pparams = params;
3987
3988         SSVAL(params,0,0);
3989
3990         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3991   
3992         return(-1);
3993 }
3994
3995 /****************************************************************************
3996  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3997  We don't actually do this - we just send a null response.
3998 ****************************************************************************/
3999
4000 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4001                                         char **pparams, int total_params, char **ppdata, int total_data,
4002                                         unsigned int max_data_bytes)
4003 {
4004         static uint16 fnf_handle = 257;
4005         char *params = *pparams;
4006         uint16 info_level;
4007
4008         if (total_params < 6)
4009                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4010
4011         info_level = SVAL(params,4);
4012         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4013
4014         switch (info_level) {
4015                 case 1:
4016                 case 2:
4017                         break;
4018                 default:
4019                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
4020         }
4021
4022         /* Realloc the parameter and data sizes */
4023         params = SMB_REALLOC(*pparams,6);
4024         if(params == NULL) 
4025                 return ERROR_DOS(ERRDOS,ERRnomem);
4026         *pparams = params;
4027
4028         SSVAL(params,0,fnf_handle);
4029         SSVAL(params,2,0); /* No changes */
4030         SSVAL(params,4,0); /* No EA errors */
4031
4032         fnf_handle++;
4033
4034         if(fnf_handle == 0)
4035                 fnf_handle = 257;
4036
4037         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4038   
4039         return(-1);
4040 }
4041
4042 /****************************************************************************
4043  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
4044  changes). Currently this does nothing.
4045 ****************************************************************************/
4046
4047 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4048                                         char **pparams, int total_params, char **ppdata, int total_data,
4049                                         unsigned int max_data_bytes)
4050 {
4051         char *params = *pparams;
4052
4053         DEBUG(3,("call_trans2findnotifynext\n"));
4054
4055         /* Realloc the parameter and data sizes */
4056         params = SMB_REALLOC(*pparams,4);
4057         if(params == NULL)
4058                 return ERROR_DOS(ERRDOS,ERRnomem);
4059         *pparams = params;
4060
4061         SSVAL(params,0,0); /* No changes */
4062         SSVAL(params,2,0); /* No EA errors */
4063
4064         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4065   
4066         return(-1);
4067 }
4068
4069 /****************************************************************************
4070  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4071 ****************************************************************************/
4072
4073 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4074                                         char **pparams, int total_params, char **ppdata, int total_data,
4075                                         unsigned int max_data_bytes)
4076 {
4077         char *params = *pparams;
4078         pstring pathname;
4079         int reply_size = 0;
4080         int max_referral_level;
4081
4082         DEBUG(10,("call_trans2getdfsreferral\n"));
4083
4084         if (total_params < 2)
4085                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4086
4087         max_referral_level = SVAL(params,0);
4088
4089         if(!lp_host_msdfs())
4090                 return ERROR_DOS(ERRDOS,ERRbadfunc);
4091
4092         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4093         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4094                 return UNIXERROR(ERRDOS,ERRbadfile);
4095     
4096         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4097         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4098
4099         return(-1);
4100 }
4101
4102 #define LMCAT_SPL       0x53
4103 #define LMFUNC_GETJOBID 0x60
4104
4105 /****************************************************************************
4106  Reply to a TRANS2_IOCTL - used for OS/2 printing.
4107 ****************************************************************************/
4108
4109 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4110                                         char **pparams, int total_params, char **ppdata, int total_data,
4111                                         unsigned int max_data_bytes)
4112 {
4113         char *pdata = *ppdata;
4114         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4115
4116         /* check for an invalid fid before proceeding */
4117         
4118         if (!fsp)                                
4119                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
4120
4121         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4122                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4123                 pdata = SMB_REALLOC(*ppdata, 32);
4124                 if(pdata == NULL)
4125                         return ERROR_DOS(ERRDOS,ERRnomem);
4126                 *ppdata = pdata;
4127
4128                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4129                         CAN ACCEPT THIS IN UNICODE. JRA. */
4130
4131                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
4132                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4133                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4134                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4135                 return(-1);
4136         } else {
4137                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4138                 return ERROR_DOS(ERRSRV,ERRerror);
4139         }
4140 }
4141
4142 /****************************************************************************
4143  Reply to a SMBfindclose (stop trans2 directory search).
4144 ****************************************************************************/
4145
4146 int reply_findclose(connection_struct *conn,
4147                     char *inbuf,char *outbuf,int length,int bufsize)
4148 {
4149         int outsize = 0;
4150         int dptr_num=SVALS(inbuf,smb_vwv0);
4151         START_PROFILE(SMBfindclose);
4152
4153         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4154
4155         dptr_close(&dptr_num);
4156
4157         outsize = set_message(outbuf,0,0,True);
4158
4159         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4160
4161         END_PROFILE(SMBfindclose);
4162         return(outsize);
4163 }
4164
4165 /****************************************************************************
4166  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4167 ****************************************************************************/
4168
4169 int reply_findnclose(connection_struct *conn, 
4170                      char *inbuf,char *outbuf,int length,int bufsize)
4171 {
4172         int outsize = 0;
4173         int dptr_num= -1;
4174         START_PROFILE(SMBfindnclose);
4175         
4176         dptr_num = SVAL(inbuf,smb_vwv0);
4177
4178         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4179
4180         /* We never give out valid handles for a 
4181            findnotifyfirst - so any dptr_num is ok here. 
4182            Just ignore it. */
4183
4184         outsize = set_message(outbuf,0,0,True);
4185
4186         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4187
4188         END_PROFILE(SMBfindnclose);
4189         return(outsize);
4190 }
4191
4192 /****************************************************************************
4193  Reply to a SMBtranss2 - just ignore it!
4194 ****************************************************************************/
4195
4196 int reply_transs2(connection_struct *conn,
4197                   char *inbuf,char *outbuf,int length,int bufsize)
4198 {
4199         START_PROFILE(SMBtranss2);
4200         DEBUG(4,("Ignoring transs2 of length %d\n",length));
4201         END_PROFILE(SMBtranss2);
4202         return(-1);
4203 }
4204
4205 /****************************************************************************
4206  Reply to a SMBtrans2.
4207 ****************************************************************************/
4208
4209 int reply_trans2(connection_struct *conn,
4210                  char *inbuf,char *outbuf,int length,int bufsize)
4211 {
4212         int outsize = 0;
4213         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4214         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4215         unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4216 #if 0
4217         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4218         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4219         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4220         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4221         int32 timeout = IVALS(inbuf,smb_timeout);
4222 #endif
4223         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4224         unsigned int tran_call = SVAL(inbuf, smb_setup0);
4225         char *params = NULL, *data = NULL;
4226         unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4227         START_PROFILE(SMBtrans2);
4228
4229         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4230                 /* Queue this open message as we are the process of an
4231                  * oplock break.  */
4232
4233                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4234                 DEBUGADD(2,( "in oplock break state.\n"));
4235
4236                 push_oplock_pending_smb_message(inbuf, length);
4237                 END_PROFILE(SMBtrans2);
4238                 return -1;
4239         }
4240         
4241         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4242             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4243                 END_PROFILE(SMBtrans2);
4244                 return ERROR_DOS(ERRSRV,ERRaccess);
4245         }
4246
4247         outsize = set_message(outbuf,0,0,True);
4248
4249         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4250            is so as a sanity check */
4251         if (suwcnt != 1) {
4252                 /*
4253                  * Need to have rc=0 for ioctl to get job id for OS/2.
4254                  *  Network printing will fail if function is not successful.
4255                  *  Similar function in reply.c will be used if protocol
4256                  *  is LANMAN1.0 instead of LM1.2X002.
4257                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
4258                  *  outbuf doesn't have to be set(only job id is used).
4259                  */
4260                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4261                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4262                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4263                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4264                 } else {
4265                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4266                         DEBUG(2,("Transaction is %d\n",tran_call));
4267                         END_PROFILE(SMBtrans2);
4268                         ERROR_DOS(ERRDOS,ERRinvalidparam);
4269                 }
4270         }
4271     
4272         /* Allocate the space for the maximum needed parameters and data */
4273         if (total_params > 0)
4274                 params = (char *)SMB_MALLOC(total_params);
4275         if (total_data > 0)
4276                 data = (char *)SMB_MALLOC(total_data);
4277   
4278         if ((total_params && !params)  || (total_data && !data)) {
4279                 DEBUG(2,("Out of memory in reply_trans2\n"));
4280                 SAFE_FREE(params);
4281                 SAFE_FREE(data); 
4282                 END_PROFILE(SMBtrans2);
4283                 return ERROR_DOS(ERRDOS,ERRnomem);
4284         }
4285
4286         /* Copy the param and data bytes sent with this request into
4287            the params buffer */
4288         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4289         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4290
4291         if (num_params > total_params || num_data > total_data)
4292                 exit_server("invalid params in reply_trans2");
4293
4294         if(params) {
4295                 unsigned int psoff = SVAL(inbuf, smb_psoff);
4296                 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4297                         goto bad_param;
4298                 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4299                                 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4300                         goto bad_param;
4301                 memcpy( params, smb_base(inbuf) + psoff, num_params);
4302         }
4303         if(data) {
4304                 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4305                 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4306                         goto bad_param;
4307                 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4308                                 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4309                         goto bad_param;
4310                 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4311         }
4312
4313         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4314
4315         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
4316                 /* We need to send an interim response then receive the rest
4317                    of the parameter/data bytes */
4318                 outsize = set_message(outbuf,0,0,True);
4319                 srv_signing_trans_stop();
4320                 if (!send_smb(smbd_server_fd(),outbuf))
4321                         exit_server("reply_trans2: send_smb failed.");
4322
4323                 while (num_data_sofar < total_data || 
4324                        num_params_sofar < total_params) {
4325                         BOOL ret;
4326                         unsigned int param_disp;
4327                         unsigned int param_off;
4328                         unsigned int data_disp;
4329                         unsigned int data_off;
4330
4331                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4332                         
4333                         /*
4334                          * The sequence number for the trans reply is always
4335                          * based on the last secondary received.
4336                          */
4337
4338                         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4339
4340                         if ((ret && 
4341                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4342                                 outsize = set_message(outbuf,0,0,True);
4343                                 if(ret)
4344                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4345                                 else
4346                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4347                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4348                                 goto bad_param;
4349                         }
4350       
4351                         /* Revise total_params and total_data in case
4352                            they have changed downwards */
4353                         if (SVAL(inbuf, smb_tpscnt) < total_params)
4354                                 total_params = SVAL(inbuf, smb_tpscnt);
4355                         if (SVAL(inbuf, smb_tdscnt) < total_data)
4356                                 total_data = SVAL(inbuf, smb_tdscnt);
4357
4358                         num_params = SVAL(inbuf,smb_spscnt);
4359                         param_off = SVAL(inbuf, smb_spsoff);
4360                         param_disp = SVAL(inbuf, smb_spsdisp);
4361                         num_params_sofar += num_params;
4362
4363                         num_data = SVAL(inbuf, smb_sdscnt);
4364                         data_off = SVAL(inbuf, smb_sdsoff);
4365                         data_disp = SVAL(inbuf, smb_sdsdisp);
4366                         num_data_sofar += num_data;
4367
4368                         if (num_params_sofar > total_params || num_data_sofar > total_data)
4369                                 goto bad_param;
4370                         
4371                         if (num_params) {
4372                                 if (param_disp + num_params > total_params)
4373                                         goto bad_param;
4374                                 if ((param_disp + num_params < param_disp) ||
4375                                                 (param_disp + num_params < num_params))
4376                                         goto bad_param;
4377                                 if (param_disp > total_params)
4378                                         goto bad_param;
4379                                 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4380                                                 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4381                                         goto bad_param;
4382                                 if (params + param_disp < params)
4383                                         goto bad_param;
4384
4385                                 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4386                         }
4387                         if (num_data) {
4388                                 if (data_disp + num_data > total_data)
4389                                         goto bad_param;
4390                                 if ((data_disp + num_data < data_disp) ||
4391                                                 (data_disp + num_data < num_data))
4392                                         goto bad_param;
4393                                 if (data_disp > total_data)
4394                                         goto bad_param;
4395                                 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4396                                                 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4397                                         goto bad_param;
4398                                 if (data + data_disp < data)
4399                                         goto bad_param;
4400
4401                                 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4402                         }
4403                 }
4404         }
4405         
4406         if (Protocol >= PROTOCOL_NT1) {
4407                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4408         }
4409
4410         /* Now we must call the relevant TRANS2 function */
4411         switch(tran_call)  {
4412         case TRANSACT2_OPEN:
4413                 START_PROFILE_NESTED(Trans2_open);
4414                 outsize = call_trans2open(conn, inbuf, outbuf, bufsize, 
4415                                           &params, total_params, &data, total_data, max_data_bytes);
4416                 END_PROFILE_NESTED(Trans2_open);
4417                 break;
4418
4419         case TRANSACT2_FINDFIRST:
4420                 START_PROFILE_NESTED(Trans2_findfirst);
4421                 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4422                                           &params, total_params, &data, total_data, max_data_bytes);
4423                 END_PROFILE_NESTED(Trans2_findfirst);
4424                 break;
4425
4426         case TRANSACT2_FINDNEXT:
4427                 START_PROFILE_NESTED(Trans2_findnext);
4428                 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, 
4429                                           &params, total_params, &data, total_data, max_data_bytes);
4430                 END_PROFILE_NESTED(Trans2_findnext);
4431                 break;
4432
4433         case TRANSACT2_QFSINFO:
4434                 START_PROFILE_NESTED(Trans2_qfsinfo);
4435                 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4436                                           &params, total_params, &data, total_data, max_data_bytes);
4437                 END_PROFILE_NESTED(Trans2_qfsinfo);
4438             break;
4439
4440 #ifdef HAVE_SYS_QUOTAS
4441         case TRANSACT2_SETFSINFO:
4442                 START_PROFILE_NESTED(Trans2_setfsinfo);
4443                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, 
4444                                           &params, total_params, &data, total_data, max_data_bytes);
4445                 END_PROFILE_NESTED(Trans2_setfsinfo);
4446                 break;
4447 #endif
4448         case TRANSACT2_QPATHINFO:
4449         case TRANSACT2_QFILEINFO:
4450                 START_PROFILE_NESTED(Trans2_qpathinfo);
4451                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4452                                           &params, total_params, &data, total_data, max_data_bytes);
4453                 END_PROFILE_NESTED(Trans2_qpathinfo);
4454                 break;
4455         case TRANSACT2_SETPATHINFO:
4456         case TRANSACT2_SETFILEINFO:
4457                 START_PROFILE_NESTED(Trans2_setpathinfo);
4458                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4459                                           &params, total_params, &data, total_data, max_data_bytes);
4460                 END_PROFILE_NESTED(Trans2_setpathinfo);
4461                 break;
4462
4463         case TRANSACT2_FINDNOTIFYFIRST:
4464                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4465                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, 
4466                                           &params, total_params, &data, total_data, max_data_bytes);
4467                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4468                 break;
4469
4470         case TRANSACT2_FINDNOTIFYNEXT:
4471                 START_PROFILE_NESTED(Trans2_findnotifynext);
4472                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, 
4473                                           &params, total_params, &data, total_data, max_data_bytes);
4474                 END_PROFILE_NESTED(Trans2_findnotifynext);
4475                 break;
4476         case TRANSACT2_MKDIR:
4477                 START_PROFILE_NESTED(Trans2_mkdir);
4478                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4479                                           &params, total_params, &data, total_data, max_data_bytes);
4480                 END_PROFILE_NESTED(Trans2_mkdir);
4481                 break;
4482
4483         case TRANSACT2_GET_DFS_REFERRAL:
4484                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4485                 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4486                                           &params, total_params, &data, total_data, max_data_bytes);
4487                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4488                 break;
4489         case TRANSACT2_IOCTL:
4490                 START_PROFILE_NESTED(Trans2_ioctl);
4491                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4492                                           &params, total_params, &data, total_data, max_data_bytes);
4493                 END_PROFILE_NESTED(Trans2_ioctl);
4494                 break;
4495         default:
4496                 /* Error in request */
4497                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4498                 SAFE_FREE(params);
4499                 SAFE_FREE(data);
4500                 END_PROFILE(SMBtrans2);
4501                 srv_signing_trans_stop();
4502                 return ERROR_DOS(ERRSRV,ERRerror);
4503         }
4504         
4505         /* As we do not know how many data packets will need to be
4506            returned here the various call_trans2xxxx calls
4507            must send their own. Thus a call_trans2xxx routine only
4508            returns a value other than -1 when it wants to send
4509            an error packet. 
4510         */
4511         
4512         srv_signing_trans_stop();
4513
4514         SAFE_FREE(params);
4515         SAFE_FREE(data);
4516         END_PROFILE(SMBtrans2);
4517         return outsize; /* If a correct response was needed the
4518                            call_trans2xxx calls have already sent
4519                            it. If outsize != -1 then it is returning */
4520
4521   bad_param:
4522
4523         srv_signing_trans_stop();
4524         SAFE_FREE(params);
4525         SAFE_FREE(data);
4526         END_PROFILE(SMBtrans2);
4527         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4528 }