r3889: Only set mtime from pending_modtime if it's not already zero...
[tprouty/samba.git] / source / smbd / trans2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2003
5    Copyright (C) Stefan (metze) Metzmacher      2003
6
7    Extensively modified by Andrew Tridgell, 1995
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 extern int Protocol;
27 extern int smb_read_error;
28 extern fstring local_machine;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
32
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
35
36 /********************************************************************
37  Roundup a value to the nearest SMB_ROUNDUP_ALLOCATION_SIZE boundary.
38  Only do this for Windows clients.
39 ********************************************************************/
40
41 SMB_BIG_UINT smb_roundup(SMB_BIG_UINT val)
42 {
43         /* Only roundup for Windows clients. */
44         enum remote_arch_types ra_type = get_remote_arch();
45         if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
46                 val = SMB_ROUNDUP(val,SMB_ROUNDUP_ALLOCATION_SIZE);
47         }
48         return val;
49 }
50
51 /********************************************************************
52  Given a stat buffer return the allocated size on disk, taking into
53  account sparse files.
54 ********************************************************************/
55
56 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
57 {
58         SMB_BIG_UINT ret;
59
60 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
61         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
62 #else
63         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
64 #endif
65
66         if (!ret && fsp && fsp->initial_allocation_size)
67                 ret = fsp->initial_allocation_size;
68
69         ret = smb_roundup(ret);
70
71         return ret;
72 }
73
74 /****************************************************************************
75  Utility functions for dealing with extended attributes.
76 ****************************************************************************/
77
78 static const char *prohibited_ea_names[] = {
79         SAMBA_POSIX_INHERITANCE_EA_NAME,
80         SAMBA_XATTR_DOS_ATTRIB,
81         NULL
82 };
83
84 /****************************************************************************
85  Refuse to allow clients to overwrite our private xattrs.
86 ****************************************************************************/
87
88 static BOOL samba_private_attr_name(const char *unix_ea_name)
89 {
90         int i;
91
92         for (i = 0; prohibited_ea_names[i]; i++) {
93                 if (strequal( prohibited_ea_names[i], unix_ea_name))
94                         return True;
95         }
96         return False;
97 }
98
99 struct ea_list {
100         struct ea_list *next, *prev;
101         struct ea_struct ea;
102 };
103
104 /****************************************************************************
105  Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
107
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109                                 const char *fname, char *ea_name, struct ea_struct *pea)
110 {
111         /* Get the value of this xattr. Max size is 64k. */
112         size_t attr_size = 256;
113         char *val = NULL;
114         ssize_t sizeret;
115
116  again:
117
118         val = talloc_realloc(mem_ctx, val, attr_size);
119         if (!val) {
120                 return False;
121         }
122
123         if (fsp && fsp->fd != -1) {
124                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
125         } else {
126                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
127         }
128
129         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
130                 attr_size = 65536;
131                 goto again;
132         }
133
134         if (sizeret == -1) {
135                 return False;
136         }
137
138         DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
139         dump_data(10, val, sizeret);
140
141         pea->flags = 0;
142         if (strnequal(ea_name, "user.", 5)) {
143                 pea->name = &ea_name[5];
144         } else {
145                 pea->name = ea_name;
146         }
147         pea->value.data = val;
148         pea->value.length = (size_t)sizeret;
149         return True;
150 }
151
152 /****************************************************************************
153  Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
155
156 static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
157 {
158         /* Get a list of all xattrs. Max namesize is 64k. */
159         size_t ea_namelist_size = 1024;
160         char *ea_namelist;
161         char *p;
162         ssize_t sizeret;
163         int i;
164         struct ea_list *ea_list_head = NULL;
165
166         *pea_total_len = 0;
167
168         if (!lp_ea_support(SNUM(conn))) {
169                 return NULL;
170         }
171
172         for (i = 0, ea_namelist = talloc(mem_ctx, ea_namelist_size); i < 6;
173                         ea_namelist = talloc_realloc(mem_ctx, ea_namelist, ea_namelist_size), i++) {
174                 if (fsp && fsp->fd != -1) {
175                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
176                 } else {
177                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
178                 }
179
180                 if (sizeret == -1 && errno == ERANGE) {
181                         ea_namelist_size *= 2;
182                 } else {
183                         break;
184                 }
185         }
186
187         if (sizeret == -1)
188                 return NULL;
189
190         DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
191
192         if (sizeret) {
193                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
194                         struct ea_list *listp, *tmp;
195
196                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
197                                 continue;
198                 
199                         listp = talloc(mem_ctx, sizeof(struct ea_list));
200                         if (!listp)
201                                 return NULL;
202
203                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
204                                 return NULL;
205                         }
206
207                         {
208                                 fstring dos_ea_name;
209                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
210                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
211                                 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
212                                         *pea_total_len, dos_ea_name,
213                                         (unsigned int)listp->ea.value.length ));
214                         }
215                         DLIST_ADD_END(ea_list_head, listp, tmp);
216                 }
217                 /* Add on 4 for total length. */
218                 if (*pea_total_len) {
219                         *pea_total_len += 4;
220                 }
221         }
222
223         DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
224         return ea_list_head;
225 }
226
227 /****************************************************************************
228  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
229  that was filled.
230 ****************************************************************************/
231
232 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
233         connection_struct *conn, files_struct *fsp, const char *fname)
234 {
235         unsigned int ret_data_size = 4;
236         char *p = pdata;
237         size_t total_ea_len;
238         TALLOC_CTX *mem_ctx;
239         struct ea_list *ea_list;
240
241         SMB_ASSERT(total_data_size >= 4);
242
243         SIVAL(pdata,0,0);
244         if (!lp_ea_support(SNUM(conn))) {
245                 return 4;
246         }
247         mem_ctx = talloc_init("fill_ea_buffer");
248         if (!mem_ctx) {
249                 return 4;
250         }
251
252         ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
253         if (!ea_list) {
254                 talloc_destroy(mem_ctx);
255                 return 4;
256         }
257
258         if (total_ea_len > total_data_size) {
259                 talloc_destroy(mem_ctx);
260                 return 4;
261         }
262
263         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
264                 size_t dos_namelen;
265                 fstring dos_ea_name;
266                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
267                 dos_namelen = strlen(dos_ea_name);
268                 if (dos_namelen > 255 || dos_namelen == 0) {
269                         break;
270                 }
271                 if (ea_list->ea.value.length > 65535) {
272                         break;
273                 }
274                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
275                         break;
276                 }
277
278                 /* We know we have room. */
279                 SCVAL(p,0,ea_list->ea.flags);
280                 SCVAL(p,1,dos_namelen);
281                 SSVAL(p,2,ea_list->ea.value.length);
282                 fstrcpy(p+4, dos_ea_name);
283                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284
285                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
286                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
287         }
288
289         ret_data_size = PTR_DIFF(p, pdata);
290         DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
291                         ret_data_size, total_ea_len ));
292         talloc_destroy(mem_ctx);
293         SIVAL(pdata,0,ret_data_size);
294         return ret_data_size;
295 }
296
297 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
298 {
299         size_t total_ea_len = 0;
300         TALLOC_CTX *mem_ctx = NULL;
301
302         if (!lp_ea_support(SNUM(conn))) {
303                 return 0;
304         }
305         mem_ctx = talloc_init("estimate_ea_size");
306         (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
307         talloc_destroy(mem_ctx);
308         return total_ea_len;
309 }
310
311 /****************************************************************************
312  Ensure the EA name is case insensitive by matching any existing EA name.
313 ****************************************************************************/
314
315 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
316 {
317         size_t total_ea_len;
318         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
319         struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
320
321         for (; ea_list; ea_list = ea_list->next) {
322                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
323                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
324                                 &unix_ea_name[5], ea_list->ea.name));
325                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
326                         break;
327                 }
328         }
329         talloc_destroy(mem_ctx);
330 }
331
332 /****************************************************************************
333  Set or delete an extended attribute.
334 ****************************************************************************/
335
336 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
337                         char *pdata, int total_data)
338 {
339         unsigned int namelen;
340         unsigned int ealen;
341         int ret;
342         fstring unix_ea_name;
343
344         if (!lp_ea_support(SNUM(conn))) {
345                 return NT_STATUS_EAS_NOT_SUPPORTED;
346         }
347
348         if (total_data < 8) {
349                 return NT_STATUS_INVALID_PARAMETER;
350         }
351
352         if (IVAL(pdata,0) > total_data) {
353                 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
354                 return NT_STATUS_INVALID_PARAMETER;
355         }
356
357         pdata += 4;
358         namelen = CVAL(pdata,1);
359         ealen = SVAL(pdata,2);
360         pdata += 4;
361         if (total_data < 8 + namelen + 1 + ealen) {
362                 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
363                         (unsigned int)total_data, namelen, ealen));
364                 return NT_STATUS_INVALID_PARAMETER;
365         }
366
367         if (pdata[namelen] != '\0') {
368                 DEBUG(10,("set_ea: ea name not null terminated\n"));
369                 return NT_STATUS_INVALID_PARAMETER;
370         }
371
372         fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
373         pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
374         pdata += (namelen + 1);
375
376         canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
377
378         DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
379         if (ealen) {
380                 DEBUG(10,("set_ea: data :\n"));
381                 dump_data(10, pdata, ealen);
382         }
383
384         if (samba_private_attr_name(unix_ea_name)) {
385                 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
386                 return NT_STATUS_ACCESS_DENIED;
387         }
388
389         if (ealen == 0) {
390                 /* Remove the attribute. */
391                 if (fsp && (fsp->fd != -1)) {
392                         DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
393                                 unix_ea_name, fsp->fsp_name));
394                         ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
395                 } else {
396                         DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
397                                 unix_ea_name, fname));
398                         ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
399                 }
400 #ifdef ENOATTR
401                 /* Removing a non existent attribute always succeeds. */
402                 if (ret == -1 && errno == ENOATTR) {
403                         DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
404                         ret = 0;
405                 }
406 #endif
407         } else {
408                 if (fsp && (fsp->fd != -1)) {
409                         DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
410                                 unix_ea_name, fsp->fsp_name));
411                         ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
412                 } else {
413                         DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
414                                 unix_ea_name, fname));
415                         ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
416                 }
417         }
418
419         if (ret == -1) {
420 #ifdef ENOTSUP
421                 if (errno == ENOTSUP) {
422                         return NT_STATUS_EAS_NOT_SUPPORTED;
423                 }
424 #endif
425                 return map_nt_error_from_unix(errno);
426         }
427
428         return NT_STATUS_OK;
429 }
430
431 /****************************************************************************
432   Send the required number of replies back.
433   We assume all fields other than the data fields are
434   set correctly for the type of call.
435   HACK ! Always assumes smb_setup field is zero.
436 ****************************************************************************/
437
438 static int send_trans2_replies(char *outbuf,
439                         int bufsize,
440                         char *params, 
441                         int paramsize,
442                         char *pdata,
443                         int datasize)
444 {
445         /* As we are using a protocol > LANMAN1 then the max_send
446          variable must have been set in the sessetupX call.
447          This takes precedence over the max_xmit field in the
448          global struct. These different max_xmit variables should
449          be merged as this is now too confusing */
450
451         extern int max_send;
452         int data_to_send = datasize;
453         int params_to_send = paramsize;
454         int useable_space;
455         char *pp = params;
456         char *pd = pdata;
457         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
458         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
459         int data_alignment_offset = 0;
460
461         /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
462         
463         set_message(outbuf,10,0,True);
464
465         /* If there genuinely are no parameters or data to send just send the empty packet */
466
467         if(params_to_send == 0 && data_to_send == 0) {
468                 if (!send_smb(smbd_server_fd(),outbuf))
469                         exit_server("send_trans2_replies: send_smb failed.");
470                 return 0;
471         }
472
473         /* When sending params and data ensure that both are nicely aligned */
474         /* Only do this alignment when there is also data to send - else
475                 can cause NT redirector problems. */
476
477         if (((params_to_send % 4) != 0) && (data_to_send != 0))
478                 data_alignment_offset = 4 - (params_to_send % 4);
479
480         /* Space is bufsize minus Netbios over TCP header minus SMB header */
481         /* The alignment_offset is to align the param bytes on an even byte
482                 boundary. NT 4.0 Beta needs this to work correctly. */
483
484         useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
485
486         /* useable_space can never be more than max_send minus the alignment offset. */
487
488         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
489
490         while (params_to_send || data_to_send) {
491                 /* Calculate whether we will totally or partially fill this packet */
492
493                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
494
495                 /* We can never send more than useable_space */
496                 /*
497                  * Note that 'useable_space' does not include the alignment offsets,
498                  * but we must include the alignment offsets in the calculation of
499                  * the length of the data we send over the wire, as the alignment offsets
500                  * are sent here. Fix from Marc_Jacobsen@hp.com.
501                  */
502
503                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
504
505                 set_message(outbuf, 10, total_sent_thistime, True);
506
507                 /* Set total params and data to be sent */
508                 SSVAL(outbuf,smb_tprcnt,paramsize);
509                 SSVAL(outbuf,smb_tdrcnt,datasize);
510
511                 /* Calculate how many parameters and data we can fit into
512                  * this packet. Parameters get precedence
513                  */
514
515                 params_sent_thistime = MIN(params_to_send,useable_space);
516                 data_sent_thistime = useable_space - params_sent_thistime;
517                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
518
519                 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
520
521                 /* smb_proff is the offset from the start of the SMB header to the
522                         parameter bytes, however the first 4 bytes of outbuf are
523                         the Netbios over TCP header. Thus use smb_base() to subtract
524                         them from the calculation */
525
526                 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
527
528                 if(params_sent_thistime == 0)
529                         SSVAL(outbuf,smb_prdisp,0);
530                 else
531                         /* Absolute displacement of param bytes sent in this packet */
532                         SSVAL(outbuf,smb_prdisp,pp - params);
533
534                 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
535                 if(data_sent_thistime == 0) {
536                         SSVAL(outbuf,smb_droff,0);
537                         SSVAL(outbuf,smb_drdisp, 0);
538                 } else {
539                         /* The offset of the data bytes is the offset of the
540                                 parameter bytes plus the number of parameters being sent this time */
541                         SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
542                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
543                         SSVAL(outbuf,smb_drdisp, pd - pdata);
544                 }
545
546                 /* Copy the param bytes into the packet */
547
548                 if(params_sent_thistime)
549                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
550
551                 /* Copy in the data bytes */
552                 if(data_sent_thistime)
553                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
554                                 data_alignment_offset,pd,data_sent_thistime);
555
556                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
557                         params_sent_thistime, data_sent_thistime, useable_space));
558                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
559                         params_to_send, data_to_send, paramsize, datasize));
560
561                 /* Send the packet */
562                 if (!send_smb(smbd_server_fd(),outbuf))
563                         exit_server("send_trans2_replies: send_smb failed.");
564
565                 pp += params_sent_thistime;
566                 pd += data_sent_thistime;
567
568                 params_to_send -= params_sent_thistime;
569                 data_to_send -= data_sent_thistime;
570
571                 /* Sanity check */
572                 if(params_to_send < 0 || data_to_send < 0) {
573                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
574                                 params_to_send, data_to_send));
575                         return -1;
576                 }
577         }
578
579         return 0;
580 }
581
582 /****************************************************************************
583  Reply to a TRANSACT2_OPEN.
584 ****************************************************************************/
585
586 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
587                                 char **pparams, int total_params, char **ppdata, int total_data,
588                                 unsigned int max_data_bytes)
589 {
590         char *params = *pparams;
591         int16 open_mode;
592         int16 open_attr;
593         BOOL oplock_request;
594 #if 0
595         BOOL return_additional_info;
596         int16 open_sattr;
597         time_t open_time;
598 #endif
599         int16 open_ofun;
600         int32 open_size;
601         char *pname;
602         pstring fname;
603         SMB_OFF_T size=0;
604         int fmode=0,mtime=0,rmode;
605         SMB_INO_T inode = 0;
606         SMB_STRUCT_STAT sbuf;
607         int smb_action = 0;
608         BOOL bad_path = False;
609         files_struct *fsp;
610         NTSTATUS status;
611
612         /*
613          * Ensure we have enough parameters to perform the operation.
614          */
615
616         if (total_params < 29)
617                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
618
619         open_mode = SVAL(params, 2);
620         open_attr = SVAL(params,6);
621         oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
622 #if 0
623         return_additional_info = BITSETW(params,0);
624         open_sattr = SVAL(params, 4);
625         open_time = make_unix_date3(params+8);
626 #endif
627         open_ofun = SVAL(params,12);
628         open_size = IVAL(params,14);
629         pname = &params[28];
630
631         if (IS_IPC(conn))
632                 return(ERROR_DOS(ERRSRV,ERRaccess));
633
634         srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
635         if (!NT_STATUS_IS_OK(status)) {
636                 return ERROR_NT(status);
637         }
638
639         DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
640                 fname,open_mode, open_attr, open_ofun, open_size));
641
642         /* XXXX we need to handle passed times, sattr and flags */
643
644         unix_convert(fname,conn,0,&bad_path,&sbuf);
645         if (bad_path) {
646                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
647         }
648     
649         if (!check_name(fname,conn)) {
650                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
651         }
652
653         fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
654                 oplock_request, &rmode,&smb_action);
655       
656         if (!fsp) {
657                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
658                         /* We have re-scheduled this call. */
659                         clear_cached_errors();
660                         return -1;
661                 }
662                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
663         }
664
665         size = get_file_size(sbuf);
666         fmode = dos_mode(conn,fname,&sbuf);
667         mtime = sbuf.st_mtime;
668         inode = sbuf.st_ino;
669         if (fmode & aDIR) {
670                 close_file(fsp,False);
671                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
672         }
673
674         /* Realloc the size of parameters and data we will return */
675         params = Realloc(*pparams, 28);
676         if( params == NULL )
677                 return(ERROR_DOS(ERRDOS,ERRnomem));
678         *pparams = params;
679
680         memset((char *)params,'\0',28);
681         SSVAL(params,0,fsp->fnum);
682         SSVAL(params,2,fmode);
683         put_dos_date2(params,4, mtime);
684         SIVAL(params,8, (uint32)size);
685         SSVAL(params,12,rmode);
686
687         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
688                 smb_action |= EXTENDED_OPLOCK_GRANTED;
689
690         SSVAL(params,18,smb_action);
691
692         /*
693          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
694          */
695         SIVAL(params,20,inode);
696  
697         /* Send the required number of replies */
698         send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
699
700         return -1;
701 }
702
703 /*********************************************************
704  Routine to check if a given string matches exactly.
705  as a special case a mask of "." does NOT match. That
706  is required for correct wildcard semantics
707  Case can be significant or not.
708 **********************************************************/
709
710 static BOOL exact_match(char *str,char *mask, BOOL case_sig) 
711 {
712         if (mask[0] == '.' && mask[1] == 0)
713                 return False;
714         if (case_sig)   
715                 return strcmp(str,mask)==0;
716         if (StrCaseCmp(str,mask) != 0) {
717                 return False;
718         }
719         if (ms_has_wild(str)) {
720                 return False;
721         }
722         return True;
723 }
724
725 /****************************************************************************
726  Return the filetype for UNIX extensions.
727 ****************************************************************************/
728
729 static uint32 unix_filetype(mode_t mode)
730 {
731         if(S_ISREG(mode))
732                 return UNIX_TYPE_FILE;
733         else if(S_ISDIR(mode))
734                 return UNIX_TYPE_DIR;
735 #ifdef S_ISLNK
736         else if(S_ISLNK(mode))
737                 return UNIX_TYPE_SYMLINK;
738 #endif
739 #ifdef S_ISCHR
740         else if(S_ISCHR(mode))
741                 return UNIX_TYPE_CHARDEV;
742 #endif
743 #ifdef S_ISBLK
744         else if(S_ISBLK(mode))
745                 return UNIX_TYPE_BLKDEV;
746 #endif
747 #ifdef S_ISFIFO
748         else if(S_ISFIFO(mode))
749                 return UNIX_TYPE_FIFO;
750 #endif
751 #ifdef S_ISSOCK
752         else if(S_ISSOCK(mode))
753                 return UNIX_TYPE_SOCKET;
754 #endif
755
756         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
757         return UNIX_TYPE_UNKNOWN;
758 }
759
760 /****************************************************************************
761  Map wire perms onto standard UNIX permissions. Obey share restrictions.
762 ****************************************************************************/
763
764 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
765 {
766         mode_t ret = 0;
767
768         if (perms == SMB_MODE_NO_CHANGE)
769                 return pst->st_mode;
770
771         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
772         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
773         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
774         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
775         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
776         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
777         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
778         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
779         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
780 #ifdef S_ISVTX
781         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
782 #endif
783 #ifdef S_ISGID
784         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
785 #endif
786 #ifdef S_ISUID
787         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
788 #endif
789
790         if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
791                 ret &= lp_dir_mask(SNUM(conn));
792                 /* Add in force bits */
793                 ret |= lp_force_dir_mode(SNUM(conn));
794         } else {
795                 /* Apply mode mask */
796                 ret &= lp_create_mask(SNUM(conn));
797                 /* Add in force bits */
798                 ret |= lp_force_create_mode(SNUM(conn));
799         }
800
801         return ret;
802 }
803
804 /****************************************************************************
805  Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
806 ****************************************************************************/
807
808 time_t interpret_long_unix_date(char *p)
809 {
810         DEBUG(10,("interpret_long_unix_date\n"));
811         if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
812            IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
813                 return -1;
814         } else {
815                 return interpret_long_date(p);
816         }
817 }
818
819 /****************************************************************************
820  Get a level dependent lanman2 dir entry.
821 ****************************************************************************/
822
823 static BOOL get_lanman2_dir_entry(connection_struct *conn,
824                                   void *inbuf, void *outbuf,
825                                  char *path_mask,int dirtype,int info_level,
826                                  int requires_resume_key,
827                                  BOOL dont_descend,char **ppdata, 
828                                  char *base_data, int space_remaining, 
829                                  BOOL *out_of_space, BOOL *got_exact_match,
830                                  int *last_name_off)
831 {
832         const char *dname;
833         BOOL found = False;
834         SMB_STRUCT_STAT sbuf;
835         pstring mask;
836         pstring pathreal;
837         pstring fname;
838         char *p, *q, *pdata = *ppdata;
839         uint32 reskey=0;
840         int prev_dirpos=0;
841         int mode=0;
842         SMB_OFF_T file_size = 0;
843         SMB_BIG_UINT allocation_size = 0;
844         uint32 len;
845         time_t mdate=0, adate=0, cdate=0;
846         char *nameptr;
847         BOOL was_8_3;
848         int nt_extmode; /* Used for NT connections instead of mode */
849         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
850
851         *fname = 0;
852         *out_of_space = False;
853         *got_exact_match = False;
854
855         if (!conn->dirptr)
856                 return(False);
857
858         p = strrchr_m(path_mask,'/');
859         if(p != NULL) {
860                 if(p[1] == '\0')
861                         pstrcpy(mask,"*.*");
862                 else
863                         pstrcpy(mask, p+1);
864         } else
865                 pstrcpy(mask, path_mask);
866
867         while (!found) {
868                 BOOL got_match;
869
870                 /* Needed if we run out of space */
871                 prev_dirpos = TellDir(conn->dirptr);
872                 dname = ReadDirName(conn->dirptr);
873
874                 /*
875                  * Due to bugs in NT client redirectors we are not using
876                  * resume keys any more - set them to zero.
877                  * Check out the related comments in findfirst/findnext.
878                  * JRA.
879                  */
880
881                 reskey = 0;
882
883                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
884                         (long)conn->dirptr,TellDir(conn->dirptr)));
885       
886                 if (!dname) 
887                         return(False);
888
889                 pstrcpy(fname,dname);      
890
891                 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
892                         got_match = mask_match(fname, mask, conn->case_sensitive);
893
894                 if(!got_match && !mangle_is_8_3(fname, False)) {
895
896                         /*
897                          * It turns out that NT matches wildcards against
898                          * both long *and* short names. This may explain some
899                          * of the wildcard wierdness from old DOS clients
900                          * that some people have been seeing.... JRA.
901                          */
902
903                         pstring newname;
904                         pstrcpy( newname, fname);
905                         mangle_map( newname, True, False, SNUM(conn));
906                         if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
907                                 got_match = mask_match(newname, mask, conn->case_sensitive);
908                 }
909
910                 if(got_match) {
911                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
912                         if (dont_descend && !isdots)
913                                 continue;
914           
915                         pstrcpy(pathreal,conn->dirpath);
916                         if(needslash)
917                                 pstrcat(pathreal,"/");
918                         pstrcat(pathreal,dname);
919
920                         if (INFO_LEVEL_IS_UNIX(info_level)) {
921                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
922                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
923                                                 pathreal,strerror(errno)));
924                                         continue;
925                                 }
926                         } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
927
928                                 /* Needed to show the msdfs symlinks as 
929                                  * directories */
930
931                                 if(lp_host_msdfs() && 
932                                    lp_msdfs_root(SNUM(conn)) &&
933                                    is_msdfs_link(conn, pathreal, NULL, NULL,
934                                                  &sbuf)) {
935
936                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
937                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
938
939                                 } else {
940
941                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
942                                                 pathreal,strerror(errno)));
943                                         continue;
944                                 }
945                         }
946
947                         mode = dos_mode(conn,pathreal,&sbuf);
948
949                         if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
950                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
951                                 continue;
952                         }
953
954                         file_size = get_file_size(sbuf);
955                         allocation_size = get_allocation_size(NULL,&sbuf);
956                         mdate = sbuf.st_mtime;
957                         adate = sbuf.st_atime;
958                         cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
959
960                         if (lp_dos_filetime_resolution(SNUM(conn))) {
961                                 cdate &= ~1;
962                                 mdate &= ~1;
963                                 adate &= ~1;
964                         }
965
966                         if(mode & aDIR) {
967                                 /* 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 (lp_dos_filetime_resolution(SNUM(conn))) {
2544                 c_time &= ~1;
2545                 sbuf.st_atime &= ~1;
2546                 sbuf.st_ctime &= ~1;
2547                 sbuf.st_mtime &= ~1;
2548         }
2549
2550         /* NT expects the name to be in an exact form of the *full*
2551            filename. See the trans2 torture test */
2552         if (strequal(base_name,".")) {
2553                 pstrcpy(dos_fname, "\\");
2554         } else {
2555                 pstr_sprintf(dos_fname, "\\%s", fname);
2556                 string_replace(dos_fname, '/', '\\');
2557         }
2558
2559         switch (info_level) {
2560                 case SMB_INFO_STANDARD:
2561                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2562                         data_size = 22;
2563                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2564                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2565                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2566                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2567                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2568                         SSVAL(pdata,l1_attrFile,mode);
2569                         break;
2570
2571                 case SMB_INFO_QUERY_EA_SIZE:
2572                 {
2573                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2574                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2575                         data_size = 26;
2576                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2577                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2578                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2579                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2580                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2581                         SSVAL(pdata,l1_attrFile,mode);
2582                         SIVAL(pdata,l1_attrFile+2,ea_size);
2583                         break;
2584                 }
2585
2586                 case SMB_INFO_IS_NAME_VALID:
2587                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2588                         if (tran_call == TRANSACT2_QFILEINFO) {
2589                                 /* os/2 needs this ? really ?*/      
2590                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
2591                         }
2592                         data_size = 0;
2593                         param_size = 0;
2594                         break;
2595                         
2596                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2597                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2598                         data_size = 24;
2599                         put_dos_date2(pdata,0,c_time);
2600                         put_dos_date2(pdata,4,sbuf.st_atime);
2601                         put_dos_date2(pdata,8,sbuf.st_mtime);
2602                         SIVAL(pdata,12,(uint32)file_size);
2603                         SIVAL(pdata,16,(uint32)allocation_size);
2604                         SIVAL(pdata,20,mode);
2605                         break;
2606
2607                 case SMB_INFO_QUERY_ALL_EAS:
2608                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2609                         /* We have data_size bytes to put EA's into. */
2610                         data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2611                         break;
2612
2613                 case SMB_FILE_BASIC_INFORMATION:
2614                 case SMB_QUERY_FILE_BASIC_INFO:
2615
2616                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2617                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2618                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2619                         } else {
2620                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2621                                 data_size = 40;
2622                                 SIVAL(pdata,36,0);
2623                         }
2624                         put_long_date(pdata,c_time);
2625                         put_long_date(pdata+8,sbuf.st_atime);
2626                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2627                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2628                         SIVAL(pdata,32,mode);
2629
2630                         DEBUG(5,("SMB_QFBI - "));
2631                         {
2632                                 time_t create_time = c_time;
2633                                 DEBUG(5,("create: %s ", ctime(&create_time)));
2634                         }
2635                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2636                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2637                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2638                         DEBUG(5,("mode: %x\n", mode));
2639
2640                         break;
2641
2642                 case SMB_FILE_STANDARD_INFORMATION:
2643                 case SMB_QUERY_FILE_STANDARD_INFO:
2644
2645                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2646                         data_size = 24;
2647                         SOFF_T(pdata,0,allocation_size);
2648                         SOFF_T(pdata,8,file_size);
2649                         if (delete_pending & sbuf.st_nlink)
2650                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2651                         else
2652                                 SIVAL(pdata,16,sbuf.st_nlink);
2653                         SCVAL(pdata,20,0);
2654                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2655                         break;
2656
2657                 case SMB_FILE_EA_INFORMATION:
2658                 case SMB_QUERY_FILE_EA_INFO:
2659                 {
2660                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2661                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2662                         data_size = 4;
2663                         SIVAL(pdata,0,ea_size);
2664                         break;
2665                 }
2666
2667                 /* Get the 8.3 name - used if NT SMB was negotiated. */
2668                 case SMB_QUERY_FILE_ALT_NAME_INFO:
2669                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2670                 {
2671                         pstring short_name;
2672
2673                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2674                         pstrcpy(short_name,base_name);
2675                         /* Mangle if not already 8.3 */
2676                         if(!mangle_is_8_3(short_name, True)) {
2677                                 mangle_map(short_name,True,True,SNUM(conn));
2678                         }
2679                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2680                         data_size = 4 + len;
2681                         SIVAL(pdata,0,len);
2682                         break;
2683                 }
2684
2685                 case SMB_QUERY_FILE_NAME_INFO:
2686                         /*
2687                           this must be *exactly* right for ACLs on mapped drives to work
2688                          */
2689                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2690                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2691                         data_size = 4 + len;
2692                         SIVAL(pdata,0,len);
2693                         break;
2694
2695                 case SMB_FILE_ALLOCATION_INFORMATION:
2696                 case SMB_QUERY_FILE_ALLOCATION_INFO:
2697                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2698                         data_size = 8;
2699                         SOFF_T(pdata,0,allocation_size);
2700                         break;
2701
2702                 case SMB_FILE_END_OF_FILE_INFORMATION:
2703                 case SMB_QUERY_FILE_END_OF_FILEINFO:
2704                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2705                         data_size = 8;
2706                         SOFF_T(pdata,0,file_size);
2707                         break;
2708
2709                 case SMB_QUERY_FILE_ALL_INFO:
2710                 case SMB_FILE_ALL_INFORMATION:
2711                 {
2712                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2713                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2714                         put_long_date(pdata,c_time);
2715                         put_long_date(pdata+8,sbuf.st_atime);
2716                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2717                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2718                         SIVAL(pdata,32,mode);
2719                         pdata += 40;
2720                         SOFF_T(pdata,0,allocation_size);
2721                         SOFF_T(pdata,8,file_size);
2722                         if (delete_pending && sbuf.st_nlink)
2723                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2724                         else
2725                                 SIVAL(pdata,16,sbuf.st_nlink);
2726                         SCVAL(pdata,20,delete_pending);
2727                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2728                         pdata += 24;
2729                         SIVAL(pdata,0,ea_size);
2730                         pdata += 4; /* EA info */
2731                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2732                         SIVAL(pdata,0,len);
2733                         pdata += 4 + len;
2734                         data_size = PTR_DIFF(pdata,(*ppdata));
2735                         break;
2736                 }
2737                 case SMB_FILE_INTERNAL_INFORMATION:
2738                         /* This should be an index number - looks like
2739                            dev/ino to me :-) 
2740
2741                            I think this causes us to fail the IFSKIT
2742                            BasicFileInformationTest. -tpot */
2743
2744                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2745                         SIVAL(pdata,0,sbuf.st_dev);
2746                         SIVAL(pdata,4,sbuf.st_ino);
2747                         data_size = 8;
2748                         break;
2749
2750                 case SMB_FILE_ACCESS_INFORMATION:
2751                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2752                         SIVAL(pdata,0,desired_access);
2753                         data_size = 4;
2754                         break;
2755
2756                 case SMB_FILE_NAME_INFORMATION:
2757                         /* Pathname with leading '\'. */
2758                         {
2759                                 size_t byte_len;
2760                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2761                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2762                                 SIVAL(pdata,0,byte_len);
2763                                 data_size = 4 + byte_len;
2764                                 break;
2765                         }
2766
2767                 case SMB_FILE_DISPOSITION_INFORMATION:
2768                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2769                         data_size = 1;
2770                         SCVAL(pdata,0,delete_pending);
2771                         break;
2772
2773                 case SMB_FILE_POSITION_INFORMATION:
2774                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2775                         data_size = 8;
2776                         SOFF_T(pdata,0,pos);
2777                         break;
2778
2779                 case SMB_FILE_MODE_INFORMATION:
2780                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2781                         SIVAL(pdata,0,mode);
2782                         data_size = 4;
2783                         break;
2784
2785                 case SMB_FILE_ALIGNMENT_INFORMATION:
2786                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2787                         SIVAL(pdata,0,0); /* No alignment needed. */
2788                         data_size = 4;
2789                         break;
2790
2791 #if 0
2792                 /*
2793                  * NT4 server just returns "invalid query" to this - if we try to answer
2794                  * it then NTws gets a BSOD! (tridge).
2795                  * W2K seems to want this. JRA.
2796                  */
2797                 case SMB_QUERY_FILE_STREAM_INFO:
2798 #endif
2799                 case SMB_FILE_STREAM_INFORMATION:
2800                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2801                         if (mode & aDIR) {
2802                                 data_size = 0;
2803                         } else {
2804                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2805                                 SIVAL(pdata,0,0); /* ??? */
2806                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2807                                 SOFF_T(pdata,8,file_size);
2808                                 SIVAL(pdata,16,allocation_size);
2809                                 SIVAL(pdata,20,0); /* ??? */
2810                                 data_size = 24 + byte_len;
2811                         }
2812                         break;
2813
2814                 case SMB_QUERY_COMPRESSION_INFO:
2815                 case SMB_FILE_COMPRESSION_INFORMATION:
2816                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2817                         SOFF_T(pdata,0,file_size);
2818                         SIVAL(pdata,8,0); /* ??? */
2819                         SIVAL(pdata,12,0); /* ??? */
2820                         data_size = 16;
2821                         break;
2822
2823                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2824                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2825                         put_long_date(pdata,c_time);
2826                         put_long_date(pdata+8,sbuf.st_atime);
2827                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2828                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2829                         SIVAL(pdata,32,allocation_size);
2830                         SOFF_T(pdata,40,file_size);
2831                         SIVAL(pdata,48,mode);
2832                         SIVAL(pdata,52,0); /* ??? */
2833                         data_size = 56;
2834                         break;
2835
2836                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2837                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2838                         SIVAL(pdata,0,mode);
2839                         SIVAL(pdata,4,0);
2840                         data_size = 8;
2841                         break;
2842
2843                 /*
2844                  * CIFS UNIX Extensions.
2845                  */
2846
2847                 case SMB_QUERY_FILE_UNIX_BASIC:
2848
2849                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2850                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2851
2852                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
2853                         pdata += 8;
2854
2855                         SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2856                         pdata += 8;
2857
2858                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
2859                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
2860                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
2861                         pdata += 24;
2862
2863                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
2864                         SIVAL(pdata,4,0);
2865                         pdata += 8;
2866
2867                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
2868                         SIVAL(pdata,4,0);
2869                         pdata += 8;
2870
2871                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2872                         pdata += 4;
2873
2874                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
2875                         SIVAL(pdata,4,0);
2876                         pdata += 8;
2877
2878                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
2879                         SIVAL(pdata,4,0);
2880                         pdata += 8;
2881
2882                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
2883                         pdata += 8;
2884                                 
2885                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
2886                         SIVAL(pdata,4,0);
2887                         pdata += 8;
2888
2889                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
2890                         SIVAL(pdata,4,0);
2891                         pdata += 8+1;
2892                         data_size = PTR_DIFF(pdata,(*ppdata));
2893
2894                         {
2895                                 int i;
2896                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2897
2898                                 for (i=0; i<100; i++)
2899                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2900                                 DEBUG(4,("\n"));
2901                         }
2902
2903                         break;
2904
2905                 case SMB_QUERY_FILE_UNIX_LINK:
2906                         {
2907                                 pstring buffer;
2908
2909                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2910 #ifdef S_ISLNK
2911                                 if(!S_ISLNK(sbuf.st_mode))
2912                                         return(UNIXERROR(ERRSRV,ERRbadlink));
2913 #else
2914                                 return(UNIXERROR(ERRDOS,ERRbadlink));
2915 #endif
2916                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
2917                                 if (len == -1)
2918                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2919                                 buffer[len] = 0;
2920                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2921                                 pdata += len;
2922                                 data_size = PTR_DIFF(pdata,(*ppdata));
2923
2924                                 break;
2925                         }
2926
2927                 case SMB_QUERY_POSIX_ACL:
2928                         {
2929                                 SMB_ACL_T file_acl = NULL;
2930                                 SMB_ACL_T def_acl = NULL;
2931                                 uint16 num_file_acls = 0;
2932                                 uint16 num_def_acls = 0;
2933
2934                                 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
2935                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
2936                                 } else {
2937                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
2938                                 }
2939
2940                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2941                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
2942                                                 fname ));
2943                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
2944                                 }
2945
2946                                 if (S_ISDIR(sbuf.st_mode)) {
2947                                         if (fsp && fsp->is_directory) {
2948                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
2949                                         } else {
2950                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
2951                                         }
2952                                         def_acl = free_empty_sys_acl(conn, def_acl);
2953                                 }
2954
2955                                 num_file_acls = count_acl_entries(conn, file_acl);
2956                                 num_def_acls = count_acl_entries(conn, def_acl);
2957
2958                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
2959                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
2960                                                 data_size,
2961                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
2962                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
2963                                         if (file_acl) {
2964                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2965                                         }
2966                                         if (def_acl) {
2967                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2968                                         }
2969                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2970                                 }
2971
2972                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2973                                 SSVAL(pdata,2,num_file_acls);
2974                                 SSVAL(pdata,4,num_def_acls);
2975                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
2976                                         if (file_acl) {
2977                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2978                                         }
2979                                         if (def_acl) {
2980                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2981                                         }
2982                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2983                                 }
2984                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
2985                                         if (file_acl) {
2986                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2987                                         }
2988                                         if (def_acl) {
2989                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2990                                         }
2991                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2992                                 }
2993
2994                                 if (file_acl) {
2995                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2996                                 }
2997                                 if (def_acl) {
2998                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2999                                 }
3000                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3001                                 break;
3002                         }
3003
3004                 default:
3005                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3006         }
3007
3008         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3009
3010         return(-1);
3011 }
3012
3013 /****************************************************************************
3014  Deal with the internal needs of setting the delete on close flag. Note that
3015  as the tdb locking is recursive, it is safe to call this from within 
3016  open_file_shared. JRA.
3017 ****************************************************************************/
3018
3019 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3020 {
3021         if (delete_on_close) {
3022                 /*
3023                  * Only allow delete on close for writable files.
3024                  */
3025
3026                 if (dosmode & aRONLY) {
3027                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3028                                 fsp->fsp_name ));
3029                         return NT_STATUS_CANNOT_DELETE;
3030                 }
3031
3032                 /*
3033                  * Only allow delete on close for writable shares.
3034                  */
3035
3036                 if (!CAN_WRITE(fsp->conn)) {
3037                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3038                                 fsp->fsp_name ));
3039                         return NT_STATUS_ACCESS_DENIED;
3040                 }
3041
3042                 /*
3043                  * Only allow delete on close for files/directories opened with delete intent.
3044                  */
3045
3046                 if (!(fsp->desired_access & DELETE_ACCESS)) {
3047                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3048                                 fsp->fsp_name ));
3049                         return NT_STATUS_ACCESS_DENIED;
3050                 }
3051         }
3052
3053         if(fsp->is_directory) {
3054                 fsp->directory_delete_on_close = delete_on_close;
3055                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3056                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3057         } else {
3058                 fsp->delete_on_close = delete_on_close;
3059                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3060                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3061         }
3062
3063         return NT_STATUS_OK;
3064 }
3065
3066 /****************************************************************************
3067  Sets the delete on close flag over all share modes on this file.
3068  Modify the share mode entry for all files open
3069  on this device and inode to tell other smbds we have
3070  changed the delete on close flag. This will be noticed
3071  in the close code, the last closer will delete the file
3072  if flag is set.
3073 ****************************************************************************/
3074
3075 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3076 {
3077         DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3078                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3079
3080         if (fsp->is_directory || fsp->is_stat)
3081                 return NT_STATUS_OK;
3082
3083         if (lock_share_entry_fsp(fsp) == False)
3084                 return NT_STATUS_ACCESS_DENIED;
3085
3086         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3087                 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3088                         fsp->fsp_name ));
3089                 unlock_share_entry_fsp(fsp);
3090                 return NT_STATUS_ACCESS_DENIED;
3091         }
3092
3093         unlock_share_entry_fsp(fsp);
3094         return NT_STATUS_OK;
3095 }
3096
3097 /****************************************************************************
3098  Set a hard link (called by UNIX extensions and by NT rename with HARD link
3099  code.
3100 ****************************************************************************/
3101
3102 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3103 {
3104         BOOL bad_path_oldname = False;
3105         BOOL bad_path_newname = False;
3106         SMB_STRUCT_STAT sbuf1, sbuf2;
3107         pstring last_component_oldname;
3108         pstring last_component_newname;
3109         NTSTATUS status = NT_STATUS_OK;
3110
3111         ZERO_STRUCT(sbuf1);
3112         ZERO_STRUCT(sbuf2);
3113
3114         /* No wildcards. */
3115         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3116                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3117         }
3118
3119         unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3120         if (bad_path_oldname) {
3121                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3122         }
3123
3124         /* Quick check for "." and ".." */
3125         if (last_component_oldname[0] == '.') {
3126                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3127                         return NT_STATUS_OBJECT_NAME_INVALID;
3128                 }
3129         }
3130
3131         /* source must already exist. */
3132         if (!VALID_STAT(sbuf1)) {
3133                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3134         }
3135
3136         if (!check_name(oldname,conn)) {
3137                 return NT_STATUS_ACCESS_DENIED;
3138         }
3139
3140         unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3141         if (bad_path_newname) {
3142                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3143         }
3144
3145         /* Quick check for "." and ".." */
3146         if (last_component_newname[0] == '.') {
3147                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3148                         return NT_STATUS_OBJECT_NAME_INVALID;
3149                 }
3150         }
3151
3152         /* Disallow if newname already exists. */
3153         if (VALID_STAT(sbuf2)) {
3154                 return NT_STATUS_OBJECT_NAME_COLLISION;
3155         }
3156
3157         if (!check_name(newname,conn)) {
3158                 return NT_STATUS_ACCESS_DENIED;
3159         }
3160
3161         /* No links from a directory. */
3162         if (S_ISDIR(sbuf1.st_mode)) {
3163                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3164         }
3165
3166         /* Ensure this is within the share. */
3167         if (!reduce_name(conn, oldname) != 0)
3168                 return NT_STATUS_ACCESS_DENIED;
3169
3170         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3171
3172         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3173                 status = map_nt_error_from_unix(errno);
3174                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3175                                 nt_errstr(status), newname, oldname));
3176         }
3177
3178         return status;
3179 }
3180
3181 /****************************************************************************
3182  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3183 ****************************************************************************/
3184
3185 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3186                                         char **pparams, int total_params, char **ppdata, int total_data,
3187                                         unsigned int max_data_bytes)
3188 {
3189         char *params = *pparams;
3190         char *pdata = *ppdata;
3191         uint16 tran_call = SVAL(inbuf, smb_setup0);
3192         uint16 info_level;
3193         int dosmode=0;
3194         SMB_OFF_T size=0;
3195         struct utimbuf tvs;
3196         SMB_STRUCT_STAT sbuf;
3197         pstring fname;
3198         int fd = -1;
3199         BOOL bad_path = False;
3200         files_struct *fsp = NULL;
3201         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3202         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3203         mode_t unixmode = 0;
3204         NTSTATUS status = NT_STATUS_OK;
3205
3206         if (!params)
3207                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3208
3209         ZERO_STRUCT(sbuf);
3210
3211         if (tran_call == TRANSACT2_SETFILEINFO) {
3212                 if (total_params < 4)
3213                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3214
3215                 fsp = file_fsp(params,0);
3216                 info_level = SVAL(params,2);    
3217
3218                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3219                         /*
3220                          * This is actually a SETFILEINFO on a directory
3221                          * handle (returned from an NT SMB). NT5.0 seems
3222                          * to do this call. JRA.
3223                          */
3224                         pstrcpy(fname, fsp->fsp_name);
3225                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3226                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3227                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3228                         }
3229                 } else if (fsp && fsp->print_file) {
3230                         /*
3231                          * Doing a DELETE_ON_CLOSE should cancel a print job.
3232                          */
3233                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3234                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3235
3236                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3237         
3238                                 SSVAL(params,0,0);
3239                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3240                                 return(-1);
3241                         } else
3242                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3243             } else {
3244                         /*
3245                          * Original code - this is an open file.
3246                          */
3247                         CHECK_FSP(fsp,conn);
3248
3249                         pstrcpy(fname, fsp->fsp_name);
3250                         fd = fsp->fd;
3251
3252                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3253                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3254                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3255                         }
3256                 }
3257         } else {
3258                 /* set path info */
3259                 if (total_params < 6)
3260                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3261
3262                 info_level = SVAL(params,0);    
3263                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3264                 if (!NT_STATUS_IS_OK(status)) {
3265                         return ERROR_NT(status);
3266                 }
3267                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3268                 if (bad_path) {
3269                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3270                 }
3271
3272                 /*
3273                  * For CIFS UNIX extensions the target name may not exist.
3274                  */
3275
3276                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3277                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3278                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3279                 }    
3280
3281                 if(!check_name(fname, conn)) {
3282                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3283                 }
3284
3285         }
3286
3287         if (!CAN_WRITE(conn))
3288                 return ERROR_DOS(ERRSRV,ERRaccess);
3289
3290         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3291                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3292
3293         if (VALID_STAT(sbuf))
3294                 unixmode = sbuf.st_mode;
3295
3296         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3297                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3298
3299         /* Realloc the parameter and data sizes */
3300         params = Realloc(*pparams,2);
3301         if(params == NULL)
3302                 return ERROR_DOS(ERRDOS,ERRnomem);
3303         *pparams = params;
3304
3305         SSVAL(params,0,0);
3306
3307         if (fsp && fsp->pending_modtime) {
3308                 /* the pending modtime overrides the current modtime */
3309                 sbuf.st_mtime = fsp->pending_modtime;
3310         }
3311
3312         size = get_file_size(sbuf);
3313         tvs.modtime = sbuf.st_mtime;
3314         tvs.actime = sbuf.st_atime;
3315         dosmode = dos_mode(conn,fname,&sbuf);
3316         unixmode = sbuf.st_mode;
3317
3318         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3319         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3320
3321         switch (info_level) {
3322                 case SMB_INFO_STANDARD:
3323                 {
3324                         if (total_data < 12)
3325                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3326
3327                         /* access time */
3328                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3329                         /* write time */
3330                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3331                         break;
3332                 }
3333
3334                 case SMB_INFO_SET_EA:
3335                         status = set_ea(conn, fsp, fname, pdata, total_data);
3336                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3337                                 return ERROR_NT(status);
3338                         break;
3339
3340                 /* XXXX um, i don't think this is right.
3341                         it's also not in the cifs6.txt spec.
3342                 */
3343                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3344                         if (total_data < 28)
3345                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3346
3347                         tvs.actime = make_unix_date2(pdata+8);
3348                         tvs.modtime = make_unix_date2(pdata+12);
3349                         size = IVAL(pdata,16);
3350                         dosmode = IVAL(pdata,24);
3351                         break;
3352
3353                 /* XXXX nor this.  not in cifs6.txt, either. */
3354                 case SMB_INFO_QUERY_ALL_EAS:
3355                         if (total_data < 28)
3356                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3357
3358                         tvs.actime = make_unix_date2(pdata+8);
3359                         tvs.modtime = make_unix_date2(pdata+12);
3360                         size = IVAL(pdata,16);
3361                         dosmode = IVAL(pdata,24);
3362                         break;
3363
3364                 case SMB_SET_FILE_BASIC_INFO:
3365                 case SMB_FILE_BASIC_INFORMATION:
3366                 {
3367                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3368                         time_t write_time;
3369                         time_t changed_time;
3370
3371                         if (total_data < 36)
3372                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3373
3374                         /* Ignore create time at offset pdata. */
3375
3376                         /* access time */
3377                         tvs.actime = interpret_long_date(pdata+8);
3378
3379                         write_time = interpret_long_date(pdata+16);
3380                         changed_time = interpret_long_date(pdata+24);
3381
3382                         tvs.modtime = MIN(write_time, changed_time);
3383
3384                         if (write_time > tvs.modtime && write_time != 0xffffffff) {
3385                                 tvs.modtime = write_time;
3386                         }
3387                         /* Prefer a defined time to an undefined one. */
3388                         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3389                                 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3390                                         ? changed_time : write_time);
3391
3392                         /* attributes */
3393                         dosmode = IVAL(pdata,32);
3394                         break;
3395                 }
3396
3397                 case SMB_FILE_ALLOCATION_INFORMATION:
3398                 case SMB_SET_FILE_ALLOCATION_INFO:
3399                 {
3400                         int ret = -1;
3401                         SMB_BIG_UINT allocation_size;
3402
3403                         if (total_data < 8)
3404                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3405
3406                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3407 #ifdef LARGE_SMB_OFF_T
3408                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3409 #else /* LARGE_SMB_OFF_T */
3410                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3411                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3412 #endif /* LARGE_SMB_OFF_T */
3413                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3414                                         fname, (double)allocation_size ));
3415
3416                         if (allocation_size)
3417                                 allocation_size = smb_roundup(allocation_size);
3418
3419                         if(allocation_size != get_file_size(sbuf)) {
3420                                 SMB_STRUCT_STAT new_sbuf;
3421  
3422                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3423                                         fname, (double)allocation_size ));
3424  
3425                                 if (fd == -1) {
3426                                         files_struct *new_fsp = NULL;
3427                                         int access_mode = 0;
3428                                         int action = 0;
3429  
3430                                         if(global_oplock_break) {
3431                                                 /* Queue this file modify as we are the process of an oplock break.  */
3432  
3433                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3434                                                 DEBUGADD(2,( "in oplock break state.\n"));
3435  
3436                                                 push_oplock_pending_smb_message(inbuf, length);
3437                                                 return -1;
3438                                         }
3439  
3440                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3441                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
3442                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3443                                                                         FILE_ATTRIBUTE_NORMAL,
3444                                                                         INTERNAL_OPEN_ONLY, &access_mode, &action);
3445  
3446                                         if (new_fsp == NULL)
3447                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3448                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
3449                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3450                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3451                                                                         new_fsp->fnum, strerror(errno)));
3452                                                 ret = -1;
3453                                         }
3454                                         close_file(new_fsp,True);
3455                                 } else {
3456                                         ret = vfs_allocate_file_space(fsp, allocation_size);
3457                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3458                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3459                                                                         fsp->fnum, strerror(errno)));
3460                                                 ret = -1;
3461                                         }
3462                                 }
3463                                 if (ret == -1)
3464                                         return ERROR_NT(NT_STATUS_DISK_FULL);
3465
3466                                 /* Allocate can truncate size... */
3467                                 size = get_file_size(new_sbuf);
3468                         }
3469
3470                         break;
3471                 }
3472
3473                 case SMB_FILE_END_OF_FILE_INFORMATION:
3474                 case SMB_SET_FILE_END_OF_FILE_INFO:
3475                 {
3476                         if (total_data < 8)
3477                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3478
3479                         size = IVAL(pdata,0);
3480 #ifdef LARGE_SMB_OFF_T
3481                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3482 #else /* LARGE_SMB_OFF_T */
3483                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3484                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3485 #endif /* LARGE_SMB_OFF_T */
3486                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3487                         break;
3488                 }
3489
3490                 case SMB_FILE_DISPOSITION_INFORMATION:
3491                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3492                 {
3493                         BOOL delete_on_close;
3494
3495                         if (total_data < 1)
3496                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3497
3498                         delete_on_close = (CVAL(pdata,0) ? True : False);
3499
3500                         /* Just ignore this set on a path. */
3501                         if (tran_call != TRANSACT2_SETFILEINFO)
3502                                 break;
3503
3504                         if (fsp == NULL)
3505                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3506
3507                         status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3508  
3509                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3510                                 return ERROR_NT(status);
3511
3512                         /* The set is across all open files on this dev/inode pair. */
3513                         status =set_delete_on_close_over_all(fsp, delete_on_close);
3514                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3515                                 return ERROR_NT(status);
3516
3517                         break;
3518                 }
3519
3520                 case SMB_FILE_POSITION_INFORMATION:
3521                 {
3522                         SMB_BIG_UINT position_information;
3523
3524                         if (total_data < 8)
3525                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3526
3527                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3528 #ifdef LARGE_SMB_OFF_T
3529                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3530 #else /* LARGE_SMB_OFF_T */
3531                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3532                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3533 #endif /* LARGE_SMB_OFF_T */
3534                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3535                                         fname, (double)position_information ));
3536                         if (fsp)
3537                                 fsp->position_information = position_information;
3538                         break;
3539                 }
3540
3541                 /*
3542                  * CIFS UNIX extensions.
3543                  */
3544
3545                 case SMB_SET_FILE_UNIX_BASIC:
3546                 {
3547                         uint32 raw_unixmode;
3548
3549                         if (total_data < 100)
3550                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3551
3552                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3553                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3554                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
3555 #ifdef LARGE_SMB_OFF_T
3556                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3557 #else /* LARGE_SMB_OFF_T */
3558                                 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3559                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3560 #endif /* LARGE_SMB_OFF_T */
3561                         }
3562                         pdata+=24;          /* ctime & st_blocks are not changed */
3563                         tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3564                         tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3565                         pdata+=16;
3566                         set_owner = (uid_t)IVAL(pdata,0);
3567                         pdata += 8;
3568                         set_grp = (gid_t)IVAL(pdata,0);
3569                         pdata += 8;
3570                         raw_unixmode = IVAL(pdata,28);
3571                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3572                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
3573
3574                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3575 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3576                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3577
3578                         if (!VALID_STAT(sbuf)) {
3579
3580                                 /*
3581                                  * The only valid use of this is to create character and block
3582                                  * devices, and named pipes. This is deprecated (IMHO) and 
3583                                  * a new info level should be used for mknod. JRA.
3584                                  */
3585
3586                                 uint32 file_type = IVAL(pdata,0);
3587 #if defined(HAVE_MAKEDEV)
3588                                 uint32 dev_major = IVAL(pdata,4);
3589                                 uint32 dev_minor = IVAL(pdata,12);
3590 #endif
3591
3592                                 uid_t myuid = geteuid();
3593                                 gid_t mygid = getegid();
3594                                 SMB_DEV_T dev = (SMB_DEV_T)0;
3595
3596                                 if (tran_call == TRANSACT2_SETFILEINFO)
3597                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3598
3599                                 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3600                                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3601
3602 #if defined(HAVE_MAKEDEV)
3603                                 dev = makedev(dev_major, dev_minor);
3604 #endif
3605
3606                                 /* We can only create as the owner/group we are. */
3607
3608                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3609                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3610                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3611                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3612
3613                                 switch (file_type) {
3614 #if defined(S_IFIFO)
3615                                         case UNIX_TYPE_FIFO:
3616                                                 unixmode |= S_IFIFO;
3617                                                 break;
3618 #endif
3619 #if defined(S_IFSOCK)
3620                                         case UNIX_TYPE_SOCKET:
3621                                                 unixmode |= S_IFSOCK;
3622                                                 break;
3623 #endif
3624 #if defined(S_IFCHR)
3625                                         case UNIX_TYPE_CHARDEV:
3626                                                 unixmode |= S_IFCHR;
3627                                                 break;
3628 #endif
3629 #if defined(S_IFBLK)
3630                                         case UNIX_TYPE_BLKDEV:
3631                                                 unixmode |= S_IFBLK;
3632                                                 break;
3633 #endif
3634                                         default:
3635                                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3636                                 }
3637
3638                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3639 0%o for file %s\n", (double)dev, unixmode, fname ));
3640
3641                                 /* Ok - do the mknod. */
3642                                 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3643                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3644
3645                                 inherit_access_acl(conn, fname, unixmode);
3646
3647                                 SSVAL(params,0,0);
3648                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3649                                 return(-1);
3650                         }
3651
3652                         /*
3653                          * Deal with the UNIX specific mode set.
3654                          */
3655
3656                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3657                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3658                                         (unsigned int)unixmode, fname ));
3659                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3660                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3661                         }
3662
3663                         /*
3664                          * Deal with the UNIX specific uid set.
3665                          */
3666
3667                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3668                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3669                                         (unsigned int)set_owner, fname ));
3670                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3671                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3672                         }
3673
3674                         /*
3675                          * Deal with the UNIX specific gid set.
3676                          */
3677
3678                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3679                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3680                                         (unsigned int)set_owner, fname ));
3681                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3682                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3683                         }
3684                         break;
3685                 }
3686
3687                 case SMB_SET_FILE_UNIX_LINK:
3688                 {
3689                         pstring link_target;
3690                         char *newname = fname;
3691
3692                         /* Set a symbolic link. */
3693                         /* Don't allow this if follow links is false. */
3694
3695                         if (!lp_symlinks(SNUM(conn)))
3696                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3697
3698                         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3699
3700                         /* !widelinks forces the target path to be within the share. */
3701                         /* This means we can interpret the target as a pathname. */
3702                         if (!lp_widelinks(SNUM(conn))) {
3703                                 pstring rel_name;
3704                                 char *last_dirp = NULL;
3705
3706                                 unix_format(link_target);
3707                                 if (*link_target == '/') {
3708                                         /* No absolute paths allowed. */
3709                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3710                                 }
3711                                 pstrcpy(rel_name, newname);
3712                                 last_dirp = strrchr_m(rel_name, '/');
3713                                 if (last_dirp) {
3714                                         last_dirp[1] = '\0';
3715                                 } else {
3716                                         pstrcpy(rel_name, "./");
3717                                 }
3718                                 pstrcat(rel_name, link_target);
3719
3720                                 if (!check_name(rel_name, conn)) {
3721                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3722                                 }
3723                         }
3724
3725                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3726                                 fname, link_target ));
3727
3728                         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3729                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3730                         SSVAL(params,0,0);
3731                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3732                         return(-1);
3733                 }
3734
3735                 case SMB_SET_FILE_UNIX_HLINK:
3736                 {
3737                         pstring oldname;
3738                         char *newname = fname;
3739
3740                         /* Set a hard link. */
3741                         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3742                         if (!NT_STATUS_IS_OK(status)) {
3743                                 return ERROR_NT(status);
3744                         }
3745
3746                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3747                                 fname, oldname));
3748
3749                         status = hardlink_internals(conn, oldname, newname);
3750                         if (!NT_STATUS_IS_OK(status)) {
3751                                 return ERROR_NT(status);
3752                         }
3753
3754                         SSVAL(params,0,0);
3755                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3756                         return(-1);
3757                 }
3758
3759                 case SMB_FILE_RENAME_INFORMATION:
3760                 {
3761                         BOOL overwrite;
3762                         uint32 root_fid;
3763                         uint32 len;
3764                         pstring newname;
3765                         pstring base_name;
3766                         char *p;
3767
3768                         if (total_data < 12)
3769                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3770
3771                         overwrite = (CVAL(pdata,0) ? True : False);
3772                         root_fid = IVAL(pdata,4);
3773                         len = IVAL(pdata,8);
3774                         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3775                         if (!NT_STATUS_IS_OK(status)) {
3776                                 return ERROR_NT(status);
3777                         }
3778
3779                         /* Check the new name has no '/' characters. */
3780                         if (strchr_m(newname, '/'))
3781                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3782
3783                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3784
3785                         /* Create the base directory. */
3786                         pstrcpy(base_name, fname);
3787                         p = strrchr_m(base_name, '/');
3788                         if (p)
3789                                 *p = '\0';
3790                         /* Append the new name. */
3791                         pstrcat(base_name, "/");
3792                         pstrcat(base_name, newname);
3793
3794                         if (fsp) {
3795                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3796                                         fsp->fnum, fsp->fsp_name, base_name ));
3797                                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3798                         } else {
3799                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3800                                         fname, newname ));
3801                                 status = rename_internals(conn, fname, base_name, 0, overwrite);
3802                         }
3803                         if (!NT_STATUS_IS_OK(status)) {
3804                                 return ERROR_NT(status);
3805                         }
3806                         process_pending_change_notify_queue((time_t)0);
3807                         SSVAL(params,0,0);
3808                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3809                         return(-1);
3810                 }
3811
3812                 case SMB_SET_POSIX_ACL:
3813                 {
3814                         uint16 posix_acl_version;
3815                         uint16 num_file_acls;
3816                         uint16 num_def_acls;
3817                         BOOL valid_file_acls = True;
3818                         BOOL valid_def_acls = True;
3819
3820                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3821                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3822                         }
3823                         posix_acl_version = SVAL(pdata,0);
3824                         num_file_acls = SVAL(pdata,2);
3825                         num_def_acls = SVAL(pdata,4);
3826
3827                         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3828                                 valid_file_acls = False;
3829                                 num_file_acls = 0;
3830                         }
3831
3832                         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3833                                 valid_def_acls = False;
3834                                 num_def_acls = 0;
3835                         }
3836
3837                         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3838                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3839                         }
3840
3841                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3842                                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3843                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3844                         }
3845
3846                         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3847                                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3848                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3849                         }
3850
3851                         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3852                                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
3853                                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3854                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3855                         }
3856
3857                         SSVAL(params,0,0);
3858                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3859                         return(-1);
3860                 }
3861
3862                 default:
3863                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3864         }
3865
3866         /* get some defaults (no modifications) if any info is zero or -1. */
3867         if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3868                 tvs.actime = sbuf.st_atime;
3869
3870         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3871                 tvs.modtime = sbuf.st_mtime;
3872
3873         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3874         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3875         DEBUG(6,("size: %.0f ", (double)size));
3876
3877         if (dosmode) {
3878                 if (S_ISDIR(sbuf.st_mode))
3879                         dosmode |= aDIR;
3880                 else
3881                         dosmode &= ~aDIR;
3882         }
3883
3884         DEBUG(6,("dosmode: %x\n"  , dosmode));
3885
3886         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3887                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3888                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3889                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3890
3891                 /*
3892                  * Only do this test if we are not explicitly
3893                  * changing the size of a file.
3894                  */
3895                 if (!size)
3896                         size = get_file_size(sbuf);
3897         }
3898
3899         /*
3900          * Try and set the times, size and mode of this file -
3901          * if they are different from the current values
3902          */
3903         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3904                 if(fsp != NULL) {
3905                         /*
3906                          * This was a setfileinfo on an open file.
3907                          * NT does this a lot. It's actually pointless
3908                          * setting the time here, as it will be overwritten
3909                          * on the next write, so we save the request
3910                          * away and will set it on file close. JRA.
3911                          */
3912
3913                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3914                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3915                                 fsp->pending_modtime = tvs.modtime;
3916                         }
3917
3918                 } else {
3919
3920                         DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3921
3922                         if(file_utime(conn, fname, &tvs)!=0)
3923                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3924                 }
3925         }
3926
3927         /* check the mode isn't different, before changing it */
3928         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3929
3930                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3931
3932                 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3933                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3934                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3935                 }
3936         }
3937
3938         if (size != get_file_size(sbuf)) {
3939
3940                 int ret;
3941
3942                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3943                         fname, (double)size ));
3944
3945                 if (fd == -1) {
3946                         files_struct *new_fsp = NULL;
3947                         int access_mode = 0;
3948                         int action = 0;
3949
3950                         if(global_oplock_break) {
3951                                 /* Queue this file modify as we are the process of an oplock break.  */
3952
3953                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3954                                 DEBUGADD(2,( "in oplock break state.\n"));
3955
3956                                 push_oplock_pending_smb_message(inbuf, length);
3957                                 return -1;
3958                         }
3959
3960                         new_fsp = open_file_shared(conn, fname, &sbuf,
3961                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
3962                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3963                                                 FILE_ATTRIBUTE_NORMAL,
3964                                                 INTERNAL_OPEN_ONLY, &access_mode, &action);
3965         
3966                         if (new_fsp == NULL)
3967                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3968                         ret = vfs_set_filelen(new_fsp, size);
3969                         close_file(new_fsp,True);
3970                 } else {
3971                         ret = vfs_set_filelen(fsp, size);
3972                 }
3973
3974                 if (ret == -1)
3975                         return (UNIXERROR(ERRHRD,ERRdiskfull));
3976         }
3977
3978         SSVAL(params,0,0);
3979         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3980   
3981         return(-1);
3982 }
3983
3984 /****************************************************************************
3985  Reply to a TRANS2_MKDIR (make directory with extended attributes).
3986 ****************************************************************************/
3987
3988 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3989                                         char **pparams, int total_params, char **ppdata, int total_data,
3990                                         unsigned int max_data_bytes)
3991 {
3992         char *params = *pparams;
3993         pstring directory;
3994         int ret = -1;
3995         SMB_STRUCT_STAT sbuf;
3996         BOOL bad_path = False;
3997         NTSTATUS status = NT_STATUS_OK;
3998
3999         if (!CAN_WRITE(conn))
4000                 return ERROR_DOS(ERRSRV,ERRaccess);
4001
4002         if (total_params < 4)
4003                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4004
4005         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4006         if (!NT_STATUS_IS_OK(status)) {
4007                 return ERROR_NT(status);
4008         }
4009
4010         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4011
4012         unix_convert(directory,conn,0,&bad_path,&sbuf);
4013         if (bad_path) {
4014                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4015         }
4016         if (check_name(directory,conn))
4017                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
4018   
4019         if(ret < 0) {
4020                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4021                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4022         }
4023
4024         /* Realloc the parameter and data sizes */
4025         params = Realloc(*pparams,2);
4026         if(params == NULL)
4027                 return ERROR_DOS(ERRDOS,ERRnomem);
4028         *pparams = params;
4029
4030         SSVAL(params,0,0);
4031
4032         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4033   
4034         return(-1);
4035 }
4036
4037 /****************************************************************************
4038  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4039  We don't actually do this - we just send a null response.
4040 ****************************************************************************/
4041
4042 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4043                                         char **pparams, int total_params, char **ppdata, int total_data,
4044                                         unsigned int max_data_bytes)
4045 {
4046         static uint16 fnf_handle = 257;
4047         char *params = *pparams;
4048         uint16 info_level;
4049
4050         if (total_params < 6)
4051                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4052
4053         info_level = SVAL(params,4);
4054         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4055
4056         switch (info_level) {
4057                 case 1:
4058                 case 2:
4059                         break;
4060                 default:
4061                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
4062         }
4063
4064         /* Realloc the parameter and data sizes */
4065         params = Realloc(*pparams,6);
4066         if(params == NULL) 
4067                 return ERROR_DOS(ERRDOS,ERRnomem);
4068         *pparams = params;
4069
4070         SSVAL(params,0,fnf_handle);
4071         SSVAL(params,2,0); /* No changes */
4072         SSVAL(params,4,0); /* No EA errors */
4073
4074         fnf_handle++;
4075
4076         if(fnf_handle == 0)
4077                 fnf_handle = 257;
4078
4079         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4080   
4081         return(-1);
4082 }
4083
4084 /****************************************************************************
4085  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
4086  changes). Currently this does nothing.
4087 ****************************************************************************/
4088
4089 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4090                                         char **pparams, int total_params, char **ppdata, int total_data,
4091                                         unsigned int max_data_bytes)
4092 {
4093         char *params = *pparams;
4094
4095         DEBUG(3,("call_trans2findnotifynext\n"));
4096
4097         /* Realloc the parameter and data sizes */
4098         params = Realloc(*pparams,4);
4099         if(params == NULL)
4100                 return ERROR_DOS(ERRDOS,ERRnomem);
4101         *pparams = params;
4102
4103         SSVAL(params,0,0); /* No changes */
4104         SSVAL(params,2,0); /* No EA errors */
4105
4106         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4107   
4108         return(-1);
4109 }
4110
4111 /****************************************************************************
4112  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4113 ****************************************************************************/
4114
4115 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4116                                         char **pparams, int total_params, char **ppdata, int total_data,
4117                                         unsigned int max_data_bytes)
4118 {
4119         char *params = *pparams;
4120         pstring pathname;
4121         int reply_size = 0;
4122         int max_referral_level;
4123
4124         DEBUG(10,("call_trans2getdfsreferral\n"));
4125
4126         if (total_params < 2)
4127                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4128
4129         max_referral_level = SVAL(params,0);
4130
4131         if(!lp_host_msdfs())
4132                 return ERROR_DOS(ERRDOS,ERRbadfunc);
4133
4134         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4135         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4136                 return UNIXERROR(ERRDOS,ERRbadfile);
4137     
4138         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4139         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4140
4141         return(-1);
4142 }
4143
4144 #define LMCAT_SPL       0x53
4145 #define LMFUNC_GETJOBID 0x60
4146
4147 /****************************************************************************
4148  Reply to a TRANS2_IOCTL - used for OS/2 printing.
4149 ****************************************************************************/
4150
4151 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4152                                         char **pparams, int total_params, char **ppdata, int total_data,
4153                                         unsigned int max_data_bytes)
4154 {
4155         char *pdata = *ppdata;
4156         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4157
4158         /* check for an invalid fid before proceeding */
4159         
4160         if (!fsp)                                
4161                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
4162
4163         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4164                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4165                 pdata = Realloc(*ppdata, 32);
4166                 if(pdata == NULL)
4167                         return ERROR_DOS(ERRDOS,ERRnomem);
4168                 *ppdata = pdata;
4169
4170                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4171                         CAN ACCEPT THIS IN UNICODE. JRA. */
4172
4173                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
4174                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4175                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4176                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4177                 return(-1);
4178         } else {
4179                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4180                 return ERROR_DOS(ERRSRV,ERRerror);
4181         }
4182 }
4183
4184 /****************************************************************************
4185  Reply to a SMBfindclose (stop trans2 directory search).
4186 ****************************************************************************/
4187
4188 int reply_findclose(connection_struct *conn,
4189                     char *inbuf,char *outbuf,int length,int bufsize)
4190 {
4191         int outsize = 0;
4192         int dptr_num=SVALS(inbuf,smb_vwv0);
4193         START_PROFILE(SMBfindclose);
4194
4195         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4196
4197         dptr_close(&dptr_num);
4198
4199         outsize = set_message(outbuf,0,0,True);
4200
4201         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4202
4203         END_PROFILE(SMBfindclose);
4204         return(outsize);
4205 }
4206
4207 /****************************************************************************
4208  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4209 ****************************************************************************/
4210
4211 int reply_findnclose(connection_struct *conn, 
4212                      char *inbuf,char *outbuf,int length,int bufsize)
4213 {
4214         int outsize = 0;
4215         int dptr_num= -1;
4216         START_PROFILE(SMBfindnclose);
4217         
4218         dptr_num = SVAL(inbuf,smb_vwv0);
4219
4220         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4221
4222         /* We never give out valid handles for a 
4223            findnotifyfirst - so any dptr_num is ok here. 
4224            Just ignore it. */
4225
4226         outsize = set_message(outbuf,0,0,True);
4227
4228         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4229
4230         END_PROFILE(SMBfindnclose);
4231         return(outsize);
4232 }
4233
4234 /****************************************************************************
4235  Reply to a SMBtranss2 - just ignore it!
4236 ****************************************************************************/
4237
4238 int reply_transs2(connection_struct *conn,
4239                   char *inbuf,char *outbuf,int length,int bufsize)
4240 {
4241         START_PROFILE(SMBtranss2);
4242         DEBUG(4,("Ignoring transs2 of length %d\n",length));
4243         END_PROFILE(SMBtranss2);
4244         return(-1);
4245 }
4246
4247 /****************************************************************************
4248  Reply to a SMBtrans2.
4249 ****************************************************************************/
4250
4251 int reply_trans2(connection_struct *conn,
4252                  char *inbuf,char *outbuf,int length,int bufsize)
4253 {
4254         int outsize = 0;
4255         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4256         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4257         unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4258 #if 0
4259         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4260         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4261         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4262         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4263         int32 timeout = IVALS(inbuf,smb_timeout);
4264 #endif
4265         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4266         unsigned int tran_call = SVAL(inbuf, smb_setup0);
4267         char *params = NULL, *data = NULL;
4268         unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4269         START_PROFILE(SMBtrans2);
4270
4271         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4272                 /* Queue this open message as we are the process of an
4273                  * oplock break.  */
4274
4275                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4276                 DEBUGADD(2,( "in oplock break state.\n"));
4277
4278                 push_oplock_pending_smb_message(inbuf, length);
4279                 END_PROFILE(SMBtrans2);
4280                 return -1;
4281         }
4282         
4283         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4284             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4285                 END_PROFILE(SMBtrans2);
4286                 return ERROR_DOS(ERRSRV,ERRaccess);
4287         }
4288
4289         outsize = set_message(outbuf,0,0,True);
4290
4291         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4292            is so as a sanity check */
4293         if (suwcnt != 1) {
4294                 /*
4295                  * Need to have rc=0 for ioctl to get job id for OS/2.
4296                  *  Network printing will fail if function is not successful.
4297                  *  Similar function in reply.c will be used if protocol
4298                  *  is LANMAN1.0 instead of LM1.2X002.
4299                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
4300                  *  outbuf doesn't have to be set(only job id is used).
4301                  */
4302                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4303                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4304                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4305                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4306                 } else {
4307                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4308                         DEBUG(2,("Transaction is %d\n",tran_call));
4309                         END_PROFILE(SMBtrans2);
4310                         ERROR_DOS(ERRDOS,ERRinvalidparam);
4311                 }
4312         }
4313     
4314         /* Allocate the space for the maximum needed parameters and data */
4315         if (total_params > 0)
4316                 params = (char *)malloc(total_params);
4317         if (total_data > 0)
4318                 data = (char *)malloc(total_data);
4319   
4320         if ((total_params && !params)  || (total_data && !data)) {
4321                 DEBUG(2,("Out of memory in reply_trans2\n"));
4322                 SAFE_FREE(params);
4323                 SAFE_FREE(data); 
4324                 END_PROFILE(SMBtrans2);
4325                 return ERROR_DOS(ERRDOS,ERRnomem);
4326         }
4327
4328         /* Copy the param and data bytes sent with this request into
4329            the params buffer */
4330         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4331         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4332
4333         if (num_params > total_params || num_data > total_data)
4334                 exit_server("invalid params in reply_trans2");
4335
4336         if(params) {
4337                 unsigned int psoff = SVAL(inbuf, smb_psoff);
4338                 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4339                         goto bad_param;
4340                 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4341                                 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4342                         goto bad_param;
4343                 memcpy( params, smb_base(inbuf) + psoff, num_params);
4344         }
4345         if(data) {
4346                 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4347                 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4348                         goto bad_param;
4349                 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4350                                 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4351                         goto bad_param;
4352                 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4353         }
4354
4355         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4356
4357         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
4358                 /* We need to send an interim response then receive the rest
4359                    of the parameter/data bytes */
4360                 outsize = set_message(outbuf,0,0,True);
4361                 srv_signing_trans_stop();
4362                 if (!send_smb(smbd_server_fd(),outbuf))
4363                         exit_server("reply_trans2: send_smb failed.");
4364
4365                 while (num_data_sofar < total_data || 
4366                        num_params_sofar < total_params) {
4367                         BOOL ret;
4368                         unsigned int param_disp;
4369                         unsigned int param_off;
4370                         unsigned int data_disp;
4371                         unsigned int data_off;
4372
4373                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4374                         
4375                         /*
4376                          * The sequence number for the trans reply is always
4377                          * based on the last secondary received.
4378                          */
4379
4380                         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4381
4382                         if ((ret && 
4383                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4384                                 outsize = set_message(outbuf,0,0,True);
4385                                 if(ret)
4386                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4387                                 else
4388                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4389                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4390                                 goto bad_param;
4391                         }
4392       
4393                         /* Revise total_params and total_data in case
4394                            they have changed downwards */
4395                         if (SVAL(inbuf, smb_tpscnt) < total_params)
4396                                 total_params = SVAL(inbuf, smb_tpscnt);
4397                         if (SVAL(inbuf, smb_tdscnt) < total_data)
4398                                 total_data = SVAL(inbuf, smb_tdscnt);
4399
4400                         num_params = SVAL(inbuf,smb_spscnt);
4401                         param_off = SVAL(inbuf, smb_spsoff);
4402                         param_disp = SVAL(inbuf, smb_spsdisp);
4403                         num_params_sofar += num_params;
4404
4405                         num_data = SVAL(inbuf, smb_sdscnt);
4406                         data_off = SVAL(inbuf, smb_sdsoff);
4407                         data_disp = SVAL(inbuf, smb_sdsdisp);
4408                         num_data_sofar += num_data;
4409
4410                         if (num_params_sofar > total_params || num_data_sofar > total_data)
4411                                 goto bad_param;
4412                         
4413                         if (num_params) {
4414                                 if (param_disp + num_params > total_params)
4415                                         goto bad_param;
4416                                 if ((param_disp + num_params < param_disp) ||
4417                                                 (param_disp + num_params < num_params))
4418                                         goto bad_param;
4419                                 if (param_disp > total_params)
4420                                         goto bad_param;
4421                                 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4422                                                 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4423                                         goto bad_param;
4424                                 if (params + param_disp < params)
4425                                         goto bad_param;
4426
4427                                 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4428                         }
4429                         if (num_data) {
4430                                 if (data_disp + num_data > total_data)
4431                                         goto bad_param;
4432                                 if ((data_disp + num_data < data_disp) ||
4433                                                 (data_disp + num_data < num_data))
4434                                         goto bad_param;
4435                                 if (data_disp > total_data)
4436                                         goto bad_param;
4437                                 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4438                                                 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4439                                         goto bad_param;
4440                                 if (data + data_disp < data)
4441                                         goto bad_param;
4442
4443                                 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4444                         }
4445                 }
4446         }
4447         
4448         if (Protocol >= PROTOCOL_NT1) {
4449                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4450         }
4451
4452         /* Now we must call the relevant TRANS2 function */
4453         switch(tran_call)  {
4454         case TRANSACT2_OPEN:
4455                 START_PROFILE_NESTED(Trans2_open);
4456                 outsize = call_trans2open(conn, inbuf, outbuf, bufsize, 
4457                                           &params, total_params, &data, total_data, max_data_bytes);
4458                 END_PROFILE_NESTED(Trans2_open);
4459                 break;
4460
4461         case TRANSACT2_FINDFIRST:
4462                 START_PROFILE_NESTED(Trans2_findfirst);
4463                 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4464                                           &params, total_params, &data, total_data, max_data_bytes);
4465                 END_PROFILE_NESTED(Trans2_findfirst);
4466                 break;
4467
4468         case TRANSACT2_FINDNEXT:
4469                 START_PROFILE_NESTED(Trans2_findnext);
4470                 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, 
4471                                           &params, total_params, &data, total_data, max_data_bytes);
4472                 END_PROFILE_NESTED(Trans2_findnext);
4473                 break;
4474
4475         case TRANSACT2_QFSINFO:
4476                 START_PROFILE_NESTED(Trans2_qfsinfo);
4477                 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4478                                           &params, total_params, &data, total_data, max_data_bytes);
4479                 END_PROFILE_NESTED(Trans2_qfsinfo);
4480             break;
4481
4482 #ifdef HAVE_SYS_QUOTAS
4483         case TRANSACT2_SETFSINFO:
4484                 START_PROFILE_NESTED(Trans2_setfsinfo);
4485                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, 
4486                                           &params, total_params, &data, total_data, max_data_bytes);
4487                 END_PROFILE_NESTED(Trans2_setfsinfo);
4488                 break;
4489 #endif
4490         case TRANSACT2_QPATHINFO:
4491         case TRANSACT2_QFILEINFO:
4492                 START_PROFILE_NESTED(Trans2_qpathinfo);
4493                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4494                                           &params, total_params, &data, total_data, max_data_bytes);
4495                 END_PROFILE_NESTED(Trans2_qpathinfo);
4496                 break;
4497         case TRANSACT2_SETPATHINFO:
4498         case TRANSACT2_SETFILEINFO:
4499                 START_PROFILE_NESTED(Trans2_setpathinfo);
4500                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4501                                           &params, total_params, &data, total_data, max_data_bytes);
4502                 END_PROFILE_NESTED(Trans2_setpathinfo);
4503                 break;
4504
4505         case TRANSACT2_FINDNOTIFYFIRST:
4506                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4507                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, 
4508                                           &params, total_params, &data, total_data, max_data_bytes);
4509                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4510                 break;
4511
4512         case TRANSACT2_FINDNOTIFYNEXT:
4513                 START_PROFILE_NESTED(Trans2_findnotifynext);
4514                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, 
4515                                           &params, total_params, &data, total_data, max_data_bytes);
4516                 END_PROFILE_NESTED(Trans2_findnotifynext);
4517                 break;
4518         case TRANSACT2_MKDIR:
4519                 START_PROFILE_NESTED(Trans2_mkdir);
4520                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4521                                           &params, total_params, &data, total_data, max_data_bytes);
4522                 END_PROFILE_NESTED(Trans2_mkdir);
4523                 break;
4524
4525         case TRANSACT2_GET_DFS_REFERRAL:
4526                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4527                 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4528                                           &params, total_params, &data, total_data, max_data_bytes);
4529                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4530                 break;
4531         case TRANSACT2_IOCTL:
4532                 START_PROFILE_NESTED(Trans2_ioctl);
4533                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4534                                           &params, total_params, &data, total_data, max_data_bytes);
4535                 END_PROFILE_NESTED(Trans2_ioctl);
4536                 break;
4537         default:
4538                 /* Error in request */
4539                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4540                 SAFE_FREE(params);
4541                 SAFE_FREE(data);
4542                 END_PROFILE(SMBtrans2);
4543                 srv_signing_trans_stop();
4544                 return ERROR_DOS(ERRSRV,ERRerror);
4545         }
4546         
4547         /* As we do not know how many data packets will need to be
4548            returned here the various call_trans2xxxx calls
4549            must send their own. Thus a call_trans2xxx routine only
4550            returns a value other than -1 when it wants to send
4551            an error packet. 
4552         */
4553         
4554         srv_signing_trans_stop();
4555
4556         SAFE_FREE(params);
4557         SAFE_FREE(data);
4558         END_PROFILE(SMBtrans2);
4559         return outsize; /* If a correct response was needed the
4560                            call_trans2xxx calls have already sent
4561                            it. If outsize != -1 then it is returning */
4562
4563   bad_param:
4564
4565         srv_signing_trans_stop();
4566         SAFE_FREE(params);
4567         SAFE_FREE(data);
4568         END_PROFILE(SMBtrans2);
4569         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4570 }