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