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