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