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