a7bc2efb4aff3e6ea2bfd2719a96756c7a21d6d1
[nivanova/samba-autobuild/.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  Return the major devicenumber for UNIX extensions.
761 ****************************************************************************/
762
763 static uint32 unix_dev_major(SMB_DEV_T dev)
764 {
765 #if defined(HAVE_DEVICE_MAJOR_FN)
766         return (uint32)major(dev);
767 #else
768         return (uint32)(dev >> 8);
769 #endif
770 }
771
772 /****************************************************************************
773  Return the minor devicenumber for UNIX extensions.
774 ****************************************************************************/
775
776 static uint32 unix_dev_minor(SMB_DEV_T dev)
777 {
778 #if defined(HAVE_DEVICE_MINOR_FN)
779         return (uint32)minor(dev);
780 #else
781         return (uint32)(dev & 0xff);
782 #endif
783 }
784
785 /****************************************************************************
786  Map wire perms onto standard UNIX permissions. Obey share restrictions.
787 ****************************************************************************/
788
789 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
790 {
791         mode_t ret = 0;
792
793         if (perms == SMB_MODE_NO_CHANGE)
794                 return pst->st_mode;
795
796         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
797         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
798         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
799         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
800         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
801         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
802         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
803         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
804         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
805 #ifdef S_ISVTX
806         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
807 #endif
808 #ifdef S_ISGID
809         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
810 #endif
811 #ifdef S_ISUID
812         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
813 #endif
814
815         if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
816                 ret &= lp_dir_mask(SNUM(conn));
817                 /* Add in force bits */
818                 ret |= lp_force_dir_mode(SNUM(conn));
819         } else {
820                 /* Apply mode mask */
821                 ret &= lp_create_mask(SNUM(conn));
822                 /* Add in force bits */
823                 ret |= lp_force_create_mode(SNUM(conn));
824         }
825
826         return ret;
827 }
828
829 /****************************************************************************
830  Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
831 ****************************************************************************/
832
833 time_t interpret_long_unix_date(char *p)
834 {
835         DEBUG(10,("interpret_long_unix_date\n"));
836         if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
837            IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
838                 return -1;
839         } else {
840                 return interpret_long_date(p);
841         }
842 }
843
844 /****************************************************************************
845  Get a level dependent lanman2 dir entry.
846 ****************************************************************************/
847
848 static BOOL get_lanman2_dir_entry(connection_struct *conn,
849                                   void *inbuf, void *outbuf,
850                                  char *path_mask,int dirtype,int info_level,
851                                  int requires_resume_key,
852                                  BOOL dont_descend,char **ppdata, 
853                                  char *base_data, int space_remaining, 
854                                  BOOL *out_of_space, BOOL *got_exact_match,
855                                  int *last_name_off)
856 {
857         const char *dname;
858         BOOL found = False;
859         SMB_STRUCT_STAT sbuf;
860         pstring mask;
861         pstring pathreal;
862         pstring fname;
863         char *p, *q, *pdata = *ppdata;
864         uint32 reskey=0;
865         int prev_dirpos=0;
866         int mode=0;
867         SMB_OFF_T file_size = 0;
868         SMB_BIG_UINT allocation_size = 0;
869         uint32 len;
870         time_t mdate=0, adate=0, cdate=0;
871         char *nameptr;
872         BOOL was_8_3;
873         int nt_extmode; /* Used for NT connections instead of mode */
874         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
875
876         *fname = 0;
877         *out_of_space = False;
878         *got_exact_match = False;
879
880         if (!conn->dirptr)
881                 return(False);
882
883         p = strrchr_m(path_mask,'/');
884         if(p != NULL) {
885                 if(p[1] == '\0')
886                         pstrcpy(mask,"*.*");
887                 else
888                         pstrcpy(mask, p+1);
889         } else
890                 pstrcpy(mask, path_mask);
891
892         while (!found) {
893                 BOOL got_match;
894
895                 /* Needed if we run out of space */
896                 prev_dirpos = TellDir(conn->dirptr);
897                 dname = ReadDirName(conn->dirptr);
898
899                 /*
900                  * Due to bugs in NT client redirectors we are not using
901                  * resume keys any more - set them to zero.
902                  * Check out the related comments in findfirst/findnext.
903                  * JRA.
904                  */
905
906                 reskey = 0;
907
908                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
909                         (long)conn->dirptr,TellDir(conn->dirptr)));
910       
911                 if (!dname) 
912                         return(False);
913
914                 pstrcpy(fname,dname);      
915
916                 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
917                         got_match = mask_match(fname, mask, conn->case_sensitive);
918
919                 if(!got_match && !mangle_is_8_3(fname, False)) {
920
921                         /*
922                          * It turns out that NT matches wildcards against
923                          * both long *and* short names. This may explain some
924                          * of the wildcard wierdness from old DOS clients
925                          * that some people have been seeing.... JRA.
926                          */
927
928                         pstring newname;
929                         pstrcpy( newname, fname);
930                         mangle_map( newname, True, False, SNUM(conn));
931                         if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
932                                 got_match = mask_match(newname, mask, conn->case_sensitive);
933                 }
934
935                 if(got_match) {
936                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
937                         if (dont_descend && !isdots)
938                                 continue;
939           
940                         pstrcpy(pathreal,conn->dirpath);
941                         if(needslash)
942                                 pstrcat(pathreal,"/");
943                         pstrcat(pathreal,dname);
944
945                         if (INFO_LEVEL_IS_UNIX(info_level)) {
946                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
947                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
948                                                 pathreal,strerror(errno)));
949                                         continue;
950                                 }
951                         } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
952
953                                 /* Needed to show the msdfs symlinks as 
954                                  * directories */
955
956                                 if(lp_host_msdfs() && 
957                                    lp_msdfs_root(SNUM(conn)) &&
958                                    is_msdfs_link(conn, pathreal, NULL, NULL,
959                                                  &sbuf)) {
960
961                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
962                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
963
964                                 } else {
965
966                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
967                                                 pathreal,strerror(errno)));
968                                         continue;
969                                 }
970                         }
971
972                         mode = dos_mode(conn,pathreal,&sbuf);
973
974                         if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
975                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
976                                 continue;
977                         }
978
979                         file_size = get_file_size(sbuf);
980                         allocation_size = get_allocation_size(NULL,&sbuf);
981                         mdate = sbuf.st_mtime;
982                         adate = sbuf.st_atime;
983                         cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
984
985                         if (lp_dos_filetime_resolution(SNUM(conn))) {
986                                 cdate &= ~1;
987                                 mdate &= ~1;
988                                 adate &= ~1;
989                         }
990
991                         if(mode & aDIR)
992                                 file_size = 0;
993
994                         DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
995           
996                         found = True;
997                 }
998         }
999
1000         mangle_map(fname,False,True,SNUM(conn));
1001
1002         p = pdata;
1003         nameptr = p;
1004
1005         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1006
1007         switch (info_level) {
1008                 case SMB_INFO_STANDARD:
1009                         DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
1010                         if(requires_resume_key) {
1011                                 SIVAL(p,0,reskey);
1012                                 p += 4;
1013                         }
1014                         put_dos_date2(p,l1_fdateCreation,cdate);
1015                         put_dos_date2(p,l1_fdateLastAccess,adate);
1016                         put_dos_date2(p,l1_fdateLastWrite,mdate);
1017                         SIVAL(p,l1_cbFile,(uint32)file_size);
1018                         SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1019                         SSVAL(p,l1_attrFile,mode);
1020                         p += l1_achName;
1021                         nameptr = p;
1022                         p += align_string(outbuf, p, 0);
1023                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1024                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1025                                 if (len > 2) {
1026                                         SCVAL(nameptr, -1, len - 2);
1027                                 } else {
1028                                         SCVAL(nameptr, -1, 0);
1029                                 }
1030                         } else {
1031                                 if (len > 1) {
1032                                         SCVAL(nameptr, -1, len - 1);
1033                                 } else {
1034                                         SCVAL(nameptr, -1, 0);
1035                                 }
1036                         }
1037                         p += len;
1038                         break;
1039
1040                 case SMB_INFO_QUERY_EA_SIZE:
1041                         DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1042                         if(requires_resume_key) {
1043                                 SIVAL(p,0,reskey);
1044                                 p += 4;
1045                         }
1046                         put_dos_date2(p,l2_fdateCreation,cdate);
1047                         put_dos_date2(p,l2_fdateLastAccess,adate);
1048                         put_dos_date2(p,l2_fdateLastWrite,mdate);
1049                         SIVAL(p,l2_cbFile,(uint32)file_size);
1050                         SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1051                         SSVAL(p,l2_attrFile,mode);
1052                         {
1053                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1054                                 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1055                         }
1056                         p += l2_achName;
1057                         nameptr = p - 1;
1058                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1059                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1060                                 if (len > 2) {
1061                                         len -= 2;
1062                                 } else {
1063                                         len = 0;
1064                                 }
1065                         } else {
1066                                 if (len > 1) {
1067                                         len -= 1;
1068                                 } else {
1069                                         len = 0;
1070                                 }
1071                         }
1072                         SCVAL(nameptr,0,len);
1073                         p += len;
1074                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1075                         break;
1076
1077                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1078                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1079                         was_8_3 = mangle_is_8_3(fname, True);
1080                         p += 4;
1081                         SIVAL(p,0,reskey); p += 4;
1082                         put_long_date(p,cdate); p += 8;
1083                         put_long_date(p,adate); p += 8;
1084                         put_long_date(p,mdate); p += 8;
1085                         put_long_date(p,mdate); p += 8;
1086                         SOFF_T(p,0,file_size); p += 8;
1087                         SOFF_T(p,0,allocation_size); p += 8;
1088                         SIVAL(p,0,nt_extmode); p += 4;
1089                         q = p; p += 4; /* q is placeholder for name length. */
1090                         {
1091                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1092                                 SIVAL(p,0,ea_size); /* Extended attributes */
1093                                 p += 4;
1094                         }
1095                         /* Clear the short name buffer. This is
1096                          * IMPORTANT as not doing so will trigger
1097                          * a Win2k client bug. JRA.
1098                          */
1099                         memset(p,'\0',26);
1100                         if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1101                                 pstring mangled_name;
1102                                 pstrcpy(mangled_name, fname);
1103                                 mangle_map(mangled_name,True,True,SNUM(conn));
1104                                 mangled_name[12] = 0;
1105                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1106                                 SSVAL(p, 0, len);
1107                         } else {
1108                                 SSVAL(p,0,0);
1109                                 *(p+2) = 0;
1110                         }
1111                         p += 2 + 24;
1112                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1113                         SIVAL(q,0,len);
1114                         p += len;
1115                         len = PTR_DIFF(p, pdata);
1116                         len = (len + 3) & ~3;
1117                         SIVAL(pdata,0,len);
1118                         p = pdata + len;
1119                         break;
1120
1121                 case SMB_FIND_FILE_DIRECTORY_INFO:
1122                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1123                         p += 4;
1124                         SIVAL(p,0,reskey); p += 4;
1125                         put_long_date(p,cdate); p += 8;
1126                         put_long_date(p,adate); p += 8;
1127                         put_long_date(p,mdate); p += 8;
1128                         put_long_date(p,mdate); p += 8;
1129                         SOFF_T(p,0,file_size); p += 8;
1130                         SOFF_T(p,0,allocation_size); p += 8;
1131                         SIVAL(p,0,nt_extmode); p += 4;
1132                         len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1133                         SIVAL(p,0,len);
1134                         p += 4 + len;
1135                         len = PTR_DIFF(p, pdata);
1136                         len = (len + 3) & ~3;
1137                         SIVAL(pdata,0,len);
1138                         p = pdata + len;
1139                         break;
1140       
1141                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1142                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1143                         p += 4;
1144                         SIVAL(p,0,reskey); p += 4;
1145                         put_long_date(p,cdate); p += 8;
1146                         put_long_date(p,adate); p += 8;
1147                         put_long_date(p,mdate); p += 8;
1148                         put_long_date(p,mdate); p += 8;
1149                         SOFF_T(p,0,file_size); p += 8;
1150                         SOFF_T(p,0,allocation_size); p += 8;
1151                         SIVAL(p,0,nt_extmode); p += 4;
1152                         q = p; p += 4; /* q is placeholder for name length. */
1153                         {
1154                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1155                                 SIVAL(p,0,ea_size); /* Extended attributes */
1156                                 p +=4;
1157                         }
1158                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1159                         SIVAL(q, 0, len);
1160                         p += len;
1161
1162                         len = PTR_DIFF(p, pdata);
1163                         len = (len + 3) & ~3;
1164                         SIVAL(pdata,0,len);
1165                         p = pdata + len;
1166                         break;
1167
1168                 case SMB_FIND_FILE_NAMES_INFO:
1169                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1170                         p += 4;
1171                         SIVAL(p,0,reskey); p += 4;
1172                         p += 4;
1173                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1174                            acl on a dir (tridge) */
1175                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1176                         SIVAL(p, -4, len);
1177                         p += len;
1178                         len = PTR_DIFF(p, pdata);
1179                         len = (len + 3) & ~3;
1180                         SIVAL(pdata,0,len);
1181                         p = pdata + len;
1182                         break;
1183
1184                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1185                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1186                         p += 4;
1187                         SIVAL(p,0,reskey); p += 4;
1188                         put_long_date(p,cdate); p += 8;
1189                         put_long_date(p,adate); p += 8;
1190                         put_long_date(p,mdate); p += 8;
1191                         put_long_date(p,mdate); p += 8;
1192                         SOFF_T(p,0,file_size); p += 8;
1193                         SOFF_T(p,0,allocation_size); p += 8;
1194                         SIVAL(p,0,nt_extmode); p += 4;
1195                         q = p; p += 4; /* q is placeholder for name length. */
1196                         {
1197                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1198                                 SIVAL(p,0,ea_size); /* Extended attributes */
1199                                 p +=4;
1200                         }
1201                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1202                         SIVAL(p,0,sbuf.st_dev); p += 4;
1203                         SIVAL(p,0,sbuf.st_ino); p += 4;
1204                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1205                         SIVAL(q, 0, len);
1206                         p += len; 
1207                         len = PTR_DIFF(p, pdata);
1208                         len = (len + 3) & ~3;
1209                         SIVAL(pdata,0,len);
1210                         p = pdata + len;
1211                         break;
1212
1213                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1214                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1215                         was_8_3 = mangle_is_8_3(fname, True);
1216                         p += 4;
1217                         SIVAL(p,0,reskey); p += 4;
1218                         put_long_date(p,cdate); p += 8;
1219                         put_long_date(p,adate); p += 8;
1220                         put_long_date(p,mdate); p += 8;
1221                         put_long_date(p,mdate); p += 8;
1222                         SOFF_T(p,0,file_size); p += 8;
1223                         SOFF_T(p,0,allocation_size); p += 8;
1224                         SIVAL(p,0,nt_extmode); p += 4;
1225                         q = p; p += 4; /* q is placeholder for name length */
1226                         {
1227                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1228                                 SIVAL(p,0,ea_size); /* Extended attributes */
1229                                 p +=4;
1230                         }
1231                         /* Clear the short name buffer. This is
1232                          * IMPORTANT as not doing so will trigger
1233                          * a Win2k client bug. JRA.
1234                          */
1235                         memset(p,'\0',26);
1236                         if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1237                                 pstring mangled_name;
1238                                 pstrcpy(mangled_name, fname);
1239                                 mangle_map(mangled_name,True,True,SNUM(conn));
1240                                 mangled_name[12] = 0;
1241                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1242                                 SSVAL(p, 0, len);
1243                         } else {
1244                                 SSVAL(p,0,0);
1245                                 *(p+2) = 0;
1246                         }
1247                         p += 26;
1248                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1249                         SIVAL(p,0,sbuf.st_dev); p += 4;
1250                         SIVAL(p,0,sbuf.st_ino); p += 4;
1251                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1252                         SIVAL(q,0,len);
1253                         p += len;
1254                         len = PTR_DIFF(p, pdata);
1255                         len = (len + 3) & ~3;
1256                         SIVAL(pdata,0,len);
1257                         p = pdata + len;
1258                         break;
1259
1260                 /* CIFS UNIX Extension. */
1261
1262                 case SMB_FIND_FILE_UNIX:
1263                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1264                         p+= 4;
1265                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1266
1267                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1268                         SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
1269                         p+= 8;
1270
1271                         SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1272                         p+= 8;
1273
1274                         put_long_date(p,sbuf.st_ctime);       /* Inode change Time 64 Bit */
1275                         put_long_date(p+8,sbuf.st_atime);     /* Last access time 64 Bit */
1276                         put_long_date(p+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
1277                         p+= 24;
1278
1279                         SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
1280                         SIVAL(p,4,0);
1281                         p+= 8;
1282
1283                         SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
1284                         SIVAL(p,4,0);
1285                         p+= 8;
1286
1287                         SIVAL(p,0,unix_filetype(sbuf.st_mode));
1288                         p+= 4;
1289
1290                         SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
1291                         SIVAL(p,4,0);
1292                         p+= 8;
1293
1294                         SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
1295                         SIVAL(p,4,0);
1296                         p+= 8;
1297
1298                         SINO_T(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
1299                         p+= 8;
1300
1301                         SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
1302                         SIVAL(p,4,0);
1303                         p+= 8;
1304
1305                         SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
1306                         SIVAL(p,4,0);
1307                         p+= 8;
1308
1309                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1310                         p += len;
1311
1312                         len = PTR_DIFF(p, pdata);
1313                         len = (len + 3) & ~3;
1314                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1315                         p = pdata + len;
1316                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1317
1318                         break;
1319
1320                 default:      
1321                         return(False);
1322         }
1323
1324
1325         if (PTR_DIFF(p,pdata) > space_remaining) {
1326                 /* Move the dirptr back to prev_dirpos */
1327                 SeekDir(conn->dirptr, prev_dirpos);
1328                 *out_of_space = True;
1329                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1330                 return False; /* Not finished - just out of space */
1331         }
1332
1333         /* Setup the last_filename pointer, as an offset from base_data */
1334         *last_name_off = PTR_DIFF(nameptr,base_data);
1335         /* Advance the data pointer to the next slot */
1336         *ppdata = p;
1337
1338         return(found);
1339 }
1340
1341 /****************************************************************************
1342  Reply to a TRANS2_FINDFIRST.
1343 ****************************************************************************/
1344
1345 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
1346                                 char **pparams, int total_params, char **ppdata, int total_data)
1347 {
1348         /* We must be careful here that we don't return more than the
1349                 allowed number of data bytes. If this means returning fewer than
1350                 maxentries then so be it. We assume that the redirector has
1351                 enough room for the fixed number of parameter bytes it has
1352                 requested. */
1353         uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1354         char *params = *pparams;
1355         char *pdata = *ppdata;
1356         int dirtype = SVAL(params,0);
1357         int maxentries = SVAL(params,2);
1358         BOOL close_after_first = BITSETW(params+4,0);
1359         BOOL close_if_end = BITSETW(params+4,1);
1360         BOOL requires_resume_key = BITSETW(params+4,2);
1361         int info_level = SVAL(params,6);
1362         pstring directory;
1363         pstring mask;
1364         char *p, *wcard;
1365         int last_name_off=0;
1366         int dptr_num = -1;
1367         int numentries = 0;
1368         int i;
1369         BOOL finished = False;
1370         BOOL dont_descend = False;
1371         BOOL out_of_space = False;
1372         int space_remaining;
1373         BOOL bad_path = False;
1374         SMB_STRUCT_STAT sbuf;
1375         NTSTATUS ntstatus = NT_STATUS_OK;
1376
1377         if (total_params < 12)
1378                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1379
1380         *directory = *mask = 0;
1381
1382         DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1383 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1384                 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1385                 info_level, max_data_bytes));
1386   
1387         switch (info_level) {
1388                 case SMB_INFO_STANDARD:
1389                 case SMB_INFO_QUERY_EA_SIZE:
1390                 case SMB_FIND_FILE_DIRECTORY_INFO:
1391                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1392                 case SMB_FIND_FILE_NAMES_INFO:
1393                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1394                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1395                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1396                         break;
1397                 case SMB_FIND_FILE_UNIX:
1398                         if (!lp_unix_extensions())
1399                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1400                         break;
1401                 default:
1402                         return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1403         }
1404
1405         srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1406         if (!NT_STATUS_IS_OK(ntstatus)) {
1407                 return ERROR_NT(ntstatus);
1408         }
1409
1410         RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1411
1412         unix_convert(directory,conn,0,&bad_path,&sbuf);
1413         if (bad_path) {
1414                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1415         }
1416         if(!check_name(directory,conn)) {
1417                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1418         }
1419
1420         p = strrchr_m(directory,'/');
1421         if(p == NULL) {
1422                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1423                 if((directory[0] == '.') && (directory[1] == '\0'))
1424                         pstrcpy(mask,"*");
1425                 else
1426                         pstrcpy(mask,directory);
1427                 pstrcpy(directory,"./");
1428         } else {
1429                 pstrcpy(mask,p+1);
1430                 *p = 0;
1431         }
1432
1433         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1434
1435         pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1436         if( pdata == NULL )
1437                 return(ERROR_DOS(ERRDOS,ERRnomem));
1438
1439         *ppdata = pdata;
1440         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1441
1442         /* Realloc the params space */
1443         params = Realloc(*pparams, 10);
1444         if (params == NULL)
1445                 return ERROR_DOS(ERRDOS,ERRnomem);
1446         *pparams = params;
1447
1448         dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1449         if (dptr_num < 0)
1450                 return(UNIXERROR(ERRDOS,ERRbadfile));
1451
1452         /* Save the wildcard match and attribs we are using on this directory - 
1453                 needed as lanman2 assumes these are being saved between calls */
1454
1455         if(!(wcard = strdup(mask))) {
1456                 dptr_close(&dptr_num);
1457                 return ERROR_DOS(ERRDOS,ERRnomem);
1458         }
1459
1460         dptr_set_wcard(dptr_num, wcard);
1461         dptr_set_attr(dptr_num, dirtype);
1462
1463         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1464
1465         /* We don't need to check for VOL here as this is returned by 
1466                 a different TRANS2 call. */
1467   
1468         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1469         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1470                 dont_descend = True;
1471     
1472         p = pdata;
1473         space_remaining = max_data_bytes;
1474         out_of_space = False;
1475
1476         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1477                 BOOL got_exact_match = False;
1478
1479                 /* this is a heuristic to avoid seeking the dirptr except when 
1480                         absolutely necessary. It allows for a filename of about 40 chars */
1481                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1482                         out_of_space = True;
1483                         finished = False;
1484                 } else {
1485                         finished = !get_lanman2_dir_entry(conn,
1486                                         inbuf, outbuf,
1487                                         mask,dirtype,info_level,
1488                                         requires_resume_key,dont_descend,
1489                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1490                                         &last_name_off);
1491                 }
1492
1493                 if (finished && out_of_space)
1494                         finished = False;
1495
1496                 if (!finished && !out_of_space)
1497                         numentries++;
1498
1499                 /*
1500                  * As an optimisation if we know we aren't looking
1501                  * for a wildcard name (ie. the name matches the wildcard exactly)
1502                  * then we can finish on any (first) match.
1503                  * This speeds up large directory searches. JRA.
1504                  */
1505
1506                 if(got_exact_match)
1507                         finished = True;
1508
1509                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1510         }
1511   
1512         /* Check if we can close the dirptr */
1513         if(close_after_first || (finished && close_if_end)) {
1514                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1515                 dptr_close(&dptr_num);
1516         }
1517
1518         /* 
1519          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
1520          * from observation of NT.
1521          */
1522
1523         if(numentries == 0) {
1524                 dptr_close(&dptr_num);
1525                 return ERROR_DOS(ERRDOS,ERRbadfile);
1526         }
1527
1528         /* At this point pdata points to numentries directory entries. */
1529
1530         /* Set up the return parameter block */
1531         SSVAL(params,0,dptr_num);
1532         SSVAL(params,2,numentries);
1533         SSVAL(params,4,finished);
1534         SSVAL(params,6,0); /* Never an EA error */
1535         SSVAL(params,8,last_name_off);
1536
1537         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1538
1539         if ((! *directory) && dptr_path(dptr_num))
1540                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1541
1542         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1543                 smb_fn_name(CVAL(inbuf,smb_com)), 
1544                 mask, directory, dirtype, numentries ) );
1545
1546         /* 
1547          * Force a name mangle here to ensure that the
1548          * mask as an 8.3 name is top of the mangled cache.
1549          * The reasons for this are subtle. Don't remove
1550          * this code unless you know what you are doing
1551          * (see PR#13758). JRA.
1552          */
1553
1554         if(!mangle_is_8_3_wildcards( mask, False))
1555                 mangle_map(mask, True, True, SNUM(conn));
1556
1557         return(-1);
1558 }
1559
1560 /****************************************************************************
1561  Reply to a TRANS2_FINDNEXT.
1562 ****************************************************************************/
1563
1564 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1565                                         char **pparams, int total_params, char **ppdata, int total_data)
1566 {
1567         /* We must be careful here that we don't return more than the
1568                 allowed number of data bytes. If this means returning fewer than
1569                 maxentries then so be it. We assume that the redirector has
1570                 enough room for the fixed number of parameter bytes it has
1571                 requested. */
1572         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1573         char *params = *pparams;
1574         char *pdata = *ppdata;
1575         int dptr_num = SVAL(params,0);
1576         int maxentries = SVAL(params,2);
1577         uint16 info_level = SVAL(params,4);
1578         uint32 resume_key = IVAL(params,6);
1579         BOOL close_after_request = BITSETW(params+10,0);
1580         BOOL close_if_end = BITSETW(params+10,1);
1581         BOOL requires_resume_key = BITSETW(params+10,2);
1582         BOOL continue_bit = BITSETW(params+10,3);
1583         pstring resume_name;
1584         pstring mask;
1585         pstring directory;
1586         char *p;
1587         uint16 dirtype;
1588         int numentries = 0;
1589         int i, last_name_off=0;
1590         BOOL finished = False;
1591         BOOL dont_descend = False;
1592         BOOL out_of_space = False;
1593         int space_remaining;
1594         NTSTATUS ntstatus = NT_STATUS_OK;
1595
1596         if (total_params < 12)
1597                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1598
1599         *mask = *directory = *resume_name = 0;
1600
1601         srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1602         if (!NT_STATUS_IS_OK(ntstatus)) {
1603                 return ERROR_NT(ntstatus);
1604         }
1605
1606         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1607 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1608 resume_key = %d resume name = %s continue=%d level = %d\n",
1609                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1610                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1611
1612         switch (info_level) {
1613                 case SMB_INFO_STANDARD:
1614                 case SMB_INFO_QUERY_EA_SIZE:
1615                 case SMB_FIND_FILE_DIRECTORY_INFO:
1616                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1617                 case SMB_FIND_FILE_NAMES_INFO:
1618                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1619                         break;
1620                 case SMB_FIND_FILE_UNIX:
1621                         if (!lp_unix_extensions())
1622                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1623                         break;
1624                 default:
1625                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1626         }
1627
1628         pdata = Realloc( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1629         if(pdata == NULL)
1630                 return ERROR_DOS(ERRDOS,ERRnomem);
1631
1632         *ppdata = pdata;
1633         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1634
1635         /* Realloc the params space */
1636         params = Realloc(*pparams, 6*SIZEOFWORD);
1637         if( params == NULL )
1638                 return ERROR_DOS(ERRDOS,ERRnomem);
1639
1640         *pparams = params;
1641
1642         /* Check that the dptr is valid */
1643         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1644                 return ERROR_DOS(ERRDOS,ERRnofiles);
1645
1646         string_set(&conn->dirpath,dptr_path(dptr_num));
1647
1648         /* Get the wildcard mask from the dptr */
1649         if((p = dptr_wcard(dptr_num))== NULL) {
1650                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1651                 return ERROR_DOS(ERRDOS,ERRnofiles);
1652         }
1653
1654         pstrcpy(mask, p);
1655         pstrcpy(directory,conn->dirpath);
1656
1657         /* Get the attr mask from the dptr */
1658         dirtype = dptr_attr(dptr_num);
1659
1660         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1661                 dptr_num, mask, dirtype, 
1662                 (long)conn->dirptr,
1663                 TellDir(conn->dirptr)));
1664
1665         /* We don't need to check for VOL here as this is returned by 
1666                 a different TRANS2 call. */
1667
1668         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1669         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1670                 dont_descend = True;
1671     
1672         p = pdata;
1673         space_remaining = max_data_bytes;
1674         out_of_space = False;
1675
1676         /* 
1677          * Seek to the correct position. We no longer use the resume key but
1678          * depend on the last file name instead.
1679          */
1680
1681         if(requires_resume_key && *resume_name && !continue_bit) {
1682
1683                 /*
1684                  * Fix for NT redirector problem triggered by resume key indexes
1685                  * changing between directory scans. We now return a resume key of 0
1686                  * and instead look for the filename to continue from (also given
1687                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1688                  * findfirst/findnext (as is usual) then the directory pointer
1689                  * should already be at the correct place. Check this by scanning
1690                  * backwards looking for an exact (ie. case sensitive) filename match. 
1691                  * If we get to the beginning of the directory and haven't found it then scan
1692                  * forwards again looking for a match. JRA.
1693                  */
1694
1695                 int current_pos, start_pos;
1696                 const char *dname = NULL;
1697                 pstring dname_pstring;
1698                 void *dirptr = conn->dirptr;
1699                 start_pos = TellDir(dirptr);
1700                 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1701                         DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1702
1703                         SeekDir(dirptr, current_pos);
1704                         dname = ReadDirName(dirptr);
1705                         if (dname) {
1706                                 /*
1707                                  * Remember, mangle_map is called by
1708                                  * get_lanman2_dir_entry(), so the resume name
1709                                  * could be mangled. Ensure we do the same
1710                                  * here.
1711                                  */
1712                                 
1713                                 /* make sure we get a copy that mangle_map can modify */
1714
1715                                 pstrcpy(dname_pstring, dname);
1716                                 mangle_map( dname_pstring, False, True, SNUM(conn));
1717                                 
1718                                 if(strcsequal( resume_name, dname_pstring)) {
1719                                         SeekDir(dirptr, current_pos+1);
1720                                         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1721                                         break;
1722                                 }
1723                         }
1724                 }
1725
1726                 /*
1727                  * Scan forward from start if not found going backwards.
1728                  */
1729
1730                 if(current_pos < 0) {
1731                         DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1732                         SeekDir(dirptr, start_pos);
1733                         for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1734
1735                                 /*
1736                                  * Remember, mangle_map is called by
1737                                  * get_lanman2_dir_entry(), so the resume name
1738                                  * could be mangled. Ensure we do the same
1739                                  * here.
1740                                  */
1741
1742                                 if(dname) {
1743                                         /* make sure we get a copy that mangle_map can modify */
1744                                         
1745                                         pstrcpy(dname_pstring, dname);
1746                                         mangle_map(dname_pstring, False, True, SNUM(conn));
1747
1748                                         if(strcsequal( resume_name, dname_pstring)) {
1749                                                 SeekDir(dirptr, current_pos+1);
1750                                                 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1751                                                 break;
1752                                         }
1753                                 }
1754                         } /* end for */
1755                 } /* end if current_pos */
1756         } /* end if requires_resume_key && !continue_bit */
1757
1758         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1759                 BOOL got_exact_match = False;
1760
1761                 /* this is a heuristic to avoid seeking the dirptr except when 
1762                         absolutely necessary. It allows for a filename of about 40 chars */
1763                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1764                         out_of_space = True;
1765                         finished = False;
1766                 } else {
1767                         finished = !get_lanman2_dir_entry(conn,
1768                                                 inbuf, outbuf,
1769                                                 mask,dirtype,info_level,
1770                                                 requires_resume_key,dont_descend,
1771                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1772                                                 &last_name_off);
1773                 }
1774
1775                 if (finished && out_of_space)
1776                         finished = False;
1777
1778                 if (!finished && !out_of_space)
1779                         numentries++;
1780
1781                 /*
1782                  * As an optimisation if we know we aren't looking
1783                  * for a wildcard name (ie. the name matches the wildcard exactly)
1784                  * then we can finish on any (first) match.
1785                  * This speeds up large directory searches. JRA.
1786                  */
1787
1788                 if(got_exact_match)
1789                         finished = True;
1790
1791                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1792         }
1793   
1794         /* Check if we can close the dirptr */
1795         if(close_after_request || (finished && close_if_end)) {
1796                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1797                 dptr_close(&dptr_num); /* This frees up the saved mask */
1798         }
1799
1800         /* Set up the return parameter block */
1801         SSVAL(params,0,numentries);
1802         SSVAL(params,2,finished);
1803         SSVAL(params,4,0); /* Never an EA error */
1804         SSVAL(params,6,last_name_off);
1805
1806         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1807
1808         if ((! *directory) && dptr_path(dptr_num))
1809                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1810
1811         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1812                 smb_fn_name(CVAL(inbuf,smb_com)), 
1813                 mask, directory, dirtype, numentries ) );
1814
1815         return(-1);
1816 }
1817
1818 /****************************************************************************
1819  Reply to a TRANS2_QFSINFO (query filesystem info).
1820 ****************************************************************************/
1821
1822 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, 
1823                         int length, int bufsize,
1824                         char **pparams, int total_params, char **ppdata, int total_data)
1825 {
1826         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1827         char *pdata = *ppdata;
1828         char *params = *pparams;
1829         uint16 info_level = SVAL(params,0);
1830         int data_len, len;
1831         SMB_STRUCT_STAT st;
1832         char *vname = volume_label(SNUM(conn));
1833         int snum = SNUM(conn);
1834         char *fstype = lp_fstype(SNUM(conn));
1835         int quota_flag = 0;
1836
1837         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1838
1839         if(SMB_VFS_STAT(conn,".",&st)!=0) {
1840                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1841                 return ERROR_DOS(ERRSRV,ERRinvdevice);
1842         }
1843
1844         pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1845         if ( pdata == NULL )
1846                 return ERROR_DOS(ERRDOS,ERRnomem);
1847
1848         *ppdata = pdata;
1849         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1850
1851         switch (info_level) {
1852                 case SMB_INFO_ALLOCATION:
1853                 {
1854                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1855                         data_len = 18;
1856                         SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); 
1857                         block_size = lp_block_size(snum);
1858                         if (bsize < block_size) {
1859                                 SMB_BIG_UINT factor = block_size/bsize;
1860                                 bsize = block_size;
1861                                 dsize /= factor;
1862                                 dfree /= factor;
1863                         }
1864                         if (bsize > block_size) {
1865                                 SMB_BIG_UINT factor = bsize/block_size;
1866                                 bsize = block_size;
1867                                 dsize *= factor;
1868                                 dfree *= factor;
1869                         }
1870                         bytes_per_sector = 512;
1871                         sectors_per_unit = bsize/bytes_per_sector;
1872
1873                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1874 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1875                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1876
1877                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
1878                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1879                         SIVAL(pdata,l1_cUnit,dsize);
1880                         SIVAL(pdata,l1_cUnitAvail,dfree);
1881                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
1882                         break;
1883                 }
1884
1885                 case SMB_INFO_VOLUME:
1886                         /* Return volume name */
1887                         /* 
1888                          * Add volume serial number - hash of a combination of
1889                          * the called hostname and the service name.
1890                          */
1891                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1892                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1893                         SCVAL(pdata,l2_vol_cch,len);
1894                         data_len = l2_vol_szVolLabel + len;
1895                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1896                                 (unsigned)st.st_ctime, len, vname));
1897                         break;
1898
1899                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1900                 case SMB_FS_ATTRIBUTE_INFORMATION:
1901
1902
1903 #if defined(HAVE_SYS_QUOTAS)
1904                         quota_flag = FILE_VOLUME_QUOTAS;
1905 #endif
1906
1907                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1908                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1909                                 quota_flag); /* FS ATTRIBUTES */
1910
1911                         SIVAL(pdata,4,255); /* Max filename component length */
1912                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1913                                 and will think we can't do long filenames */
1914                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1915                         SIVAL(pdata,8,len);
1916                         data_len = 12 + len;
1917                         break;
1918
1919                 case SMB_QUERY_FS_LABEL_INFO:
1920                 case SMB_FS_LABEL_INFORMATION:
1921                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1922                         data_len = 4 + len;
1923                         SIVAL(pdata,0,len);
1924                         break;
1925
1926                 case SMB_QUERY_FS_VOLUME_INFO:      
1927                 case SMB_FS_VOLUME_INFORMATION:
1928
1929                         /* 
1930                          * Add volume serial number - hash of a combination of
1931                          * the called hostname and the service name.
1932                          */
1933                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1934                                 (str_checksum(local_machine)<<16));
1935
1936                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1937                         SIVAL(pdata,12,len);
1938                         data_len = 18+len;
1939                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
1940                                 (int)strlen(vname),vname, lp_servicename(snum)));
1941                         break;
1942
1943                 case SMB_QUERY_FS_SIZE_INFO:
1944                 case SMB_FS_SIZE_INFORMATION:
1945                 {
1946                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1947                         data_len = 24;
1948                         SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1949                         block_size = lp_block_size(snum);
1950                         if (bsize < block_size) {
1951                                 SMB_BIG_UINT factor = block_size/bsize;
1952                                 bsize = block_size;
1953                                 dsize /= factor;
1954                                 dfree /= factor;
1955                         }
1956                         if (bsize > block_size) {
1957                                 SMB_BIG_UINT factor = bsize/block_size;
1958                                 bsize = block_size;
1959                                 dsize *= factor;
1960                                 dfree *= factor;
1961                         }
1962                         bytes_per_sector = 512;
1963                         sectors_per_unit = bsize/bytes_per_sector;
1964                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1965 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1966                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1967                         SBIG_UINT(pdata,0,dsize);
1968                         SBIG_UINT(pdata,8,dfree);
1969                         SIVAL(pdata,16,sectors_per_unit);
1970                         SIVAL(pdata,20,bytes_per_sector);
1971                         break;
1972                 }
1973
1974                 case SMB_FS_FULL_SIZE_INFORMATION:
1975                 {
1976                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1977                         data_len = 32;
1978                         SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1979                         block_size = lp_block_size(snum);
1980                         if (bsize < block_size) {
1981                                 SMB_BIG_UINT factor = block_size/bsize;
1982                                 bsize = block_size;
1983                                 dsize /= factor;
1984                                 dfree /= factor;
1985                         }
1986                         if (bsize > block_size) {
1987                                 SMB_BIG_UINT factor = bsize/block_size;
1988                                 bsize = block_size;
1989                                 dsize *= factor;
1990                                 dfree *= factor;
1991                         }
1992                         bytes_per_sector = 512;
1993                         sectors_per_unit = bsize/bytes_per_sector;
1994                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1995 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1996                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1997                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1998                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1999                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2000                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2001                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2002                         break;
2003                 }
2004
2005                 case SMB_QUERY_FS_DEVICE_INFO:
2006                 case SMB_FS_DEVICE_INFORMATION:
2007                         data_len = 8;
2008                         SIVAL(pdata,0,0); /* dev type */
2009                         SIVAL(pdata,4,0); /* characteristics */
2010                         break;
2011
2012 #ifdef HAVE_SYS_QUOTAS
2013                 case SMB_FS_QUOTA_INFORMATION:
2014                 /* 
2015                  * what we have to send --metze:
2016                  *
2017                  * Unknown1:            24 NULL bytes
2018                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2019                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2020                  * Quota Flags:         2 byte :
2021                  * Unknown3:            6 NULL bytes
2022                  *
2023                  * 48 bytes total
2024                  * 
2025                  * details for Quota Flags:
2026                  * 
2027                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2028                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2029                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2030                  * 0x0001 Enable Quotas: enable quota for this fs
2031                  *
2032                  */
2033                 {
2034                         /* we need to fake up a fsp here,
2035                          * because its not send in this call
2036                          */
2037                         files_struct fsp;
2038                         SMB_NTQUOTA_STRUCT quotas;
2039                         
2040                         ZERO_STRUCT(fsp);
2041                         ZERO_STRUCT(quotas);
2042                         
2043                         fsp.conn = conn;
2044                         fsp.fnum = -1;
2045                         fsp.fd = -1;
2046                         
2047                         /* access check */
2048                         if (current_user.uid != 0) {
2049                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2050                                         lp_servicename(SNUM(conn)),conn->user));
2051                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2052                         }
2053                         
2054                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2055                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2056                                 return ERROR_DOS(ERRSRV,ERRerror);
2057                         }
2058
2059                         data_len = 48;
2060
2061                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2062                 
2063                         /* Unknown1 24 NULL bytes*/
2064                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2065                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2066                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2067                 
2068                         /* Default Soft Quota 8 bytes */
2069                         SBIG_UINT(pdata,24,quotas.softlim);
2070
2071                         /* Default Hard Quota 8 bytes */
2072                         SBIG_UINT(pdata,32,quotas.hardlim);
2073         
2074                         /* Quota flag 2 bytes */
2075                         SSVAL(pdata,40,quotas.qflags);
2076                 
2077                         /* Unknown3 6 NULL bytes */
2078                         SSVAL(pdata,42,0);
2079                         SIVAL(pdata,44,0);
2080                         
2081                         break;
2082                 }
2083 #endif /* HAVE_SYS_QUOTAS */
2084                 case SMB_FS_OBJECTID_INFORMATION:
2085                         data_len = 64;
2086                         break;
2087
2088                 /*
2089                  * Query the version and capabilities of the CIFS UNIX extensions
2090                  * in use.
2091                  */
2092
2093                 case SMB_QUERY_CIFS_UNIX_INFO:
2094                         if (!lp_unix_extensions())
2095                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2096                         data_len = 12;
2097                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2098                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2099                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
2100                         break;
2101
2102                 case SMB_MAC_QUERY_FS_INFO:
2103                         /*
2104                          * Thursby MAC extension... ONLY on NTFS filesystems
2105                          * once we do streams then we don't need this
2106                          */
2107                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2108                                 data_len = 88;
2109                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2110                                 break;
2111                         }
2112                         /* drop through */
2113                 default:
2114                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2115         }
2116
2117
2118         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2119
2120         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2121
2122         return -1;
2123 }
2124
2125 #ifdef HAVE_SYS_QUOTAS
2126 /****************************************************************************
2127  Reply to a TRANS2_SETFSINFO (set filesystem info).
2128 ****************************************************************************/
2129
2130 static int call_trans2setfsinfo(connection_struct *conn,
2131                                 char *inbuf, char *outbuf, int length, int bufsize,
2132                                 char **pparams, int total_params, char **ppdata, int total_data)
2133 {
2134         char *pdata = *ppdata;
2135         char *params = *pparams;
2136         files_struct *fsp = NULL;
2137         uint16 info_level;
2138         int outsize;
2139         SMB_NTQUOTA_STRUCT quotas;
2140         
2141         ZERO_STRUCT(quotas);
2142
2143         DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2144
2145         /* access check */
2146         if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2147                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2148                         lp_servicename(SNUM(conn)),conn->user));
2149                 return ERROR_DOS(ERRSRV,ERRaccess);
2150         }
2151
2152         /*  */
2153         if (total_params < 4) {
2154                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2155                         total_params));
2156                 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2157         }
2158
2159         fsp = file_fsp(params,0);
2160
2161         if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2162                 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2163                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2164         }
2165
2166         info_level = SVAL(params,2);
2167
2168         switch(info_level) {
2169                 case SMB_FS_QUOTA_INFORMATION:
2170                         /* note: normaly there're 48 bytes,
2171                          * but we didn't use the last 6 bytes for now 
2172                          * --metze 
2173                          */
2174                         if (total_data < 42) {
2175                                 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2176                                         total_data));
2177                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2178                         }
2179                         
2180                         /* unknown_1 24 NULL bytes in pdata*/
2181                 
2182                         /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2183                         quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2184 #ifdef LARGE_SMB_OFF_T
2185                         quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2186 #else /* LARGE_SMB_OFF_T */
2187                         if ((IVAL(pdata,28) != 0)&&
2188                                 ((quotas.softlim != 0xFFFFFFFF)||
2189                                 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2190                                 /* more than 32 bits? */
2191                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2192                         }
2193 #endif /* LARGE_SMB_OFF_T */
2194                 
2195                         /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2196                         quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2197 #ifdef LARGE_SMB_OFF_T
2198                         quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2199 #else /* LARGE_SMB_OFF_T */
2200                         if ((IVAL(pdata,36) != 0)&&
2201                                 ((quotas.hardlim != 0xFFFFFFFF)||
2202                                 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2203                                 /* more than 32 bits? */
2204                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2205                         }
2206 #endif /* LARGE_SMB_OFF_T */
2207                 
2208                         /* quota_flags 2 bytes **/
2209                         quotas.qflags = SVAL(pdata,40);
2210                 
2211                         /* unknown_2 6 NULL bytes follow*/
2212                 
2213                         /* now set the quotas */
2214                         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2215                                 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2216                                 return ERROR_DOS(ERRSRV,ERRerror);
2217                         }
2218                         
2219                         break;
2220                 default:
2221                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2222                                 info_level));
2223                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2224                         break;
2225         }
2226
2227         /* 
2228          * sending this reply works fine, 
2229          * but I'm not sure it's the same 
2230          * like windows do...
2231          * --metze
2232          */ 
2233         outsize = set_message(outbuf,10,0,True);
2234
2235         return outsize;
2236 }
2237 #endif /* HAVE_SYS_QUOTAS */
2238
2239 /****************************************************************************
2240  *  Utility function to set bad path error.
2241  ****************************************************************************/
2242
2243 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2244 {
2245         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2246                         err, (int)bad_path ));
2247
2248         if(err == ENOENT) {
2249                 if (bad_path) {
2250                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2251                 } else {
2252                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2253                 }
2254         }
2255         return UNIXERROR(def_class,def_code);
2256 }
2257
2258 /****************************************************************************
2259  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2260  file name or file id).
2261 ****************************************************************************/
2262
2263 static int call_trans2qfilepathinfo(connection_struct *conn,
2264                                     char *inbuf, char *outbuf, int length, 
2265                                     int bufsize,
2266                                         char **pparams, int total_params, char **ppdata, int total_data)
2267 {
2268         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2269         char *params = *pparams;
2270         char *pdata = *ppdata;
2271         uint16 tran_call = SVAL(inbuf, smb_setup0);
2272         uint16 info_level;
2273         int mode=0;
2274         SMB_OFF_T file_size=0;
2275         SMB_BIG_UINT allocation_size=0;
2276         unsigned int data_size;
2277         unsigned int param_size = 2;
2278         SMB_STRUCT_STAT sbuf;
2279         pstring fname, dos_fname;
2280         char *fullpathname;
2281         char *base_name;
2282         char *p;
2283         SMB_OFF_T pos = 0;
2284         BOOL bad_path = False;
2285         BOOL delete_pending = False;
2286         int len;
2287         time_t c_time;
2288         files_struct *fsp = NULL;
2289         uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2290
2291         if (!params)
2292                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2293
2294         ZERO_STRUCT(sbuf);
2295
2296         if (tran_call == TRANSACT2_QFILEINFO) {
2297                 if (total_params < 4)
2298                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2299
2300                 fsp = file_fsp(params,0);
2301                 info_level = SVAL(params,2);
2302
2303                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2304
2305                 if(fsp && (fsp->fake_file_handle)) {
2306                         /*
2307                          * This is actually for the QUOTA_FAKE_FILE --metze
2308                          */
2309                                                 
2310                         pstrcpy(fname, fsp->fsp_name);
2311                         /* We know this name is ok, it's already passed the checks. */
2312                         
2313                 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2314                         /*
2315                          * This is actually a QFILEINFO on a directory
2316                          * handle (returned from an NT SMB). NT5.0 seems
2317                          * to do this call. JRA.
2318                          */
2319                         /* We know this name is ok, it's already passed the checks. */
2320                         pstrcpy(fname, fsp->fsp_name);
2321                   
2322                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2323                                 /* Always do lstat for UNIX calls. */
2324                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2325                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2326                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2327                                 }
2328                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2329                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2330                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2331                         }
2332
2333                         delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2334                 } else {
2335                         /*
2336                          * Original code - this is an open file.
2337                          */
2338                         CHECK_FSP(fsp,conn);
2339
2340                         pstrcpy(fname, fsp->fsp_name);
2341                         if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2342                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2343                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2344                         }
2345                         pos = fsp->position_information;
2346                         delete_pending = fsp->delete_on_close;
2347                         desired_access = fsp->desired_access;
2348                 }
2349         } else {
2350                 NTSTATUS status = NT_STATUS_OK;
2351
2352                 /* qpathinfo */
2353                 if (total_params < 6)
2354                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2355
2356                 info_level = SVAL(params,0);
2357
2358                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2359
2360                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2361                 if (!NT_STATUS_IS_OK(status)) {
2362                         return ERROR_NT(status);
2363                 }
2364
2365                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2366
2367                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2368                 if (bad_path) {
2369                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2370                 }
2371                 if (!check_name(fname,conn)) {
2372                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2373                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2374                 }
2375
2376                 if (INFO_LEVEL_IS_UNIX(info_level)) {
2377                         /* Always do lstat for UNIX calls. */
2378                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2379                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2380                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2381                         }
2382                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2383                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2384                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2385                 }
2386         }
2387
2388         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2389                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2390
2391         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2392                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2393
2394         p = strrchr_m(fname,'/'); 
2395         if (!p)
2396                 base_name = fname;
2397         else
2398                 base_name = p+1;
2399
2400         mode = dos_mode(conn,fname,&sbuf);
2401         if (!mode)
2402                 mode = FILE_ATTRIBUTE_NORMAL;
2403
2404         fullpathname = fname;
2405         file_size = get_file_size(sbuf);
2406         allocation_size = get_allocation_size(fsp,&sbuf);
2407         if (mode & aDIR)
2408                 file_size = 0;
2409
2410         params = Realloc(*pparams,2);
2411         if (params == NULL)
2412           return ERROR_DOS(ERRDOS,ERRnomem);
2413         *pparams = params;
2414         memset((char *)params,'\0',2);
2415         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2416         pdata = Realloc(*ppdata, data_size); 
2417         if ( pdata == NULL )
2418                 return ERROR_DOS(ERRDOS,ERRnomem);
2419         *ppdata = pdata;
2420
2421         if (total_data > 0 && IVAL(pdata,0) == total_data) {
2422                 /* uggh, EAs for OS2 */
2423                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2424                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2425         }
2426
2427         memset((char *)pdata,'\0',data_size);
2428
2429         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2430
2431         if (lp_dos_filetime_resolution(SNUM(conn))) {
2432                 c_time &= ~1;
2433                 sbuf.st_atime &= ~1;
2434                 sbuf.st_ctime &= ~1;
2435                 sbuf.st_mtime &= ~1;
2436         }
2437
2438         /* NT expects the name to be in an exact form of the *full*
2439            filename. See the trans2 torture test */
2440         if (strequal(base_name,".")) {
2441                 pstrcpy(dos_fname, "\\");
2442         } else {
2443                 pstr_sprintf(dos_fname, "\\%s", fname);
2444                 string_replace(dos_fname, '/', '\\');
2445         }
2446
2447         switch (info_level) {
2448                 case SMB_INFO_STANDARD:
2449                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2450                         data_size = 22;
2451                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2452                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2453                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2454                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2455                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2456                         SSVAL(pdata,l1_attrFile,mode);
2457                         break;
2458
2459                 case SMB_INFO_QUERY_EA_SIZE:
2460                 {
2461                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2462                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2463                         data_size = 26;
2464                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2465                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2466                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2467                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2468                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2469                         SSVAL(pdata,l1_attrFile,mode);
2470                         SIVAL(pdata,l1_attrFile+2,ea_size);
2471                         break;
2472                 }
2473
2474                 case SMB_INFO_IS_NAME_VALID:
2475                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2476                         if (tran_call == TRANSACT2_QFILEINFO) {
2477                                 /* os/2 needs this ? really ?*/      
2478                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
2479                         }
2480                         data_size = 0;
2481                         param_size = 0;
2482                         break;
2483                         
2484                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2485                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2486                         data_size = 24;
2487                         put_dos_date2(pdata,0,c_time);
2488                         put_dos_date2(pdata,4,sbuf.st_atime);
2489                         put_dos_date2(pdata,8,sbuf.st_mtime);
2490                         SIVAL(pdata,12,(uint32)file_size);
2491                         SIVAL(pdata,16,(uint32)allocation_size);
2492                         SIVAL(pdata,20,mode);
2493                         break;
2494
2495                 case SMB_INFO_QUERY_ALL_EAS:
2496                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2497                         /* We have data_size bytes to put EA's into. */
2498                         data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2499                         break;
2500
2501                 case SMB_FILE_BASIC_INFORMATION:
2502                 case SMB_QUERY_FILE_BASIC_INFO:
2503
2504                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2505                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2506                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2507                         } else {
2508                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2509                                 data_size = 40;
2510                                 SIVAL(pdata,36,0);
2511                         }
2512                         put_long_date(pdata,c_time);
2513                         put_long_date(pdata+8,sbuf.st_atime);
2514                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2515                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2516                         SIVAL(pdata,32,mode);
2517
2518                         DEBUG(5,("SMB_QFBI - "));
2519                         {
2520                                 time_t create_time = c_time;
2521                                 DEBUG(5,("create: %s ", ctime(&create_time)));
2522                         }
2523                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2524                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2525                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2526                         DEBUG(5,("mode: %x\n", mode));
2527
2528                         break;
2529
2530                 case SMB_FILE_STANDARD_INFORMATION:
2531                 case SMB_QUERY_FILE_STANDARD_INFO:
2532
2533                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2534                         data_size = 24;
2535                         SOFF_T(pdata,0,allocation_size);
2536                         SOFF_T(pdata,8,file_size);
2537                         if (delete_pending & sbuf.st_nlink)
2538                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2539                         else
2540                                 SIVAL(pdata,16,sbuf.st_nlink);
2541                         SCVAL(pdata,20,0);
2542                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2543                         break;
2544
2545                 case SMB_FILE_EA_INFORMATION:
2546                 case SMB_QUERY_FILE_EA_INFO:
2547                 {
2548                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2549                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2550                         data_size = 4;
2551                         SIVAL(pdata,0,ea_size);
2552                         break;
2553                 }
2554
2555                 /* Get the 8.3 name - used if NT SMB was negotiated. */
2556                 case SMB_QUERY_FILE_ALT_NAME_INFO:
2557                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2558                 {
2559                         pstring short_name;
2560
2561                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2562                         pstrcpy(short_name,base_name);
2563                         /* Mangle if not already 8.3 */
2564                         if(!mangle_is_8_3(short_name, True)) {
2565                                 mangle_map(short_name,True,True,SNUM(conn));
2566                         }
2567                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2568                         data_size = 4 + len;
2569                         SIVAL(pdata,0,len);
2570                         break;
2571                 }
2572
2573                 case SMB_QUERY_FILE_NAME_INFO:
2574                         /*
2575                           this must be *exactly* right for ACLs on mapped drives to work
2576                          */
2577                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2578                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2579                         data_size = 4 + len;
2580                         SIVAL(pdata,0,len);
2581                         break;
2582
2583                 case SMB_FILE_ALLOCATION_INFORMATION:
2584                 case SMB_QUERY_FILE_ALLOCATION_INFO:
2585                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2586                         data_size = 8;
2587                         SOFF_T(pdata,0,allocation_size);
2588                         break;
2589
2590                 case SMB_FILE_END_OF_FILE_INFORMATION:
2591                 case SMB_QUERY_FILE_END_OF_FILEINFO:
2592                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2593                         data_size = 8;
2594                         SOFF_T(pdata,0,file_size);
2595                         break;
2596
2597                 case SMB_QUERY_FILE_ALL_INFO:
2598                 case SMB_FILE_ALL_INFORMATION:
2599                 {
2600                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2601                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2602                         put_long_date(pdata,c_time);
2603                         put_long_date(pdata+8,sbuf.st_atime);
2604                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2605                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2606                         SIVAL(pdata,32,mode);
2607                         pdata += 40;
2608                         SOFF_T(pdata,0,allocation_size);
2609                         SOFF_T(pdata,8,file_size);
2610                         if (delete_pending && sbuf.st_nlink)
2611                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2612                         else
2613                                 SIVAL(pdata,16,sbuf.st_nlink);
2614                         SCVAL(pdata,20,delete_pending);
2615                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2616                         pdata += 24;
2617                         SIVAL(pdata,0,ea_size);
2618                         pdata += 4; /* EA info */
2619                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2620                         SIVAL(pdata,0,len);
2621                         pdata += 4 + len;
2622                         data_size = PTR_DIFF(pdata,(*ppdata));
2623                         break;
2624                 }
2625                 case SMB_FILE_INTERNAL_INFORMATION:
2626                         /* This should be an index number - looks like
2627                            dev/ino to me :-) 
2628
2629                            I think this causes us to fail the IFSKIT
2630                            BasicFileInformationTest. -tpot */
2631
2632                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2633                         SIVAL(pdata,0,sbuf.st_dev);
2634                         SIVAL(pdata,4,sbuf.st_ino);
2635                         data_size = 8;
2636                         break;
2637
2638                 case SMB_FILE_ACCESS_INFORMATION:
2639                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2640                         SIVAL(pdata,0,desired_access);
2641                         data_size = 4;
2642                         break;
2643
2644                 case SMB_FILE_NAME_INFORMATION:
2645                         /* Pathname with leading '\'. */
2646                         {
2647                                 size_t byte_len;
2648                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2649                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2650                                 SIVAL(pdata,0,byte_len);
2651                                 data_size = 4 + byte_len;
2652                                 break;
2653                         }
2654
2655                 case SMB_FILE_DISPOSITION_INFORMATION:
2656                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2657                         data_size = 1;
2658                         SCVAL(pdata,0,delete_pending);
2659                         break;
2660
2661                 case SMB_FILE_POSITION_INFORMATION:
2662                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2663                         data_size = 8;
2664                         SOFF_T(pdata,0,pos);
2665                         break;
2666
2667                 case SMB_FILE_MODE_INFORMATION:
2668                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2669                         SIVAL(pdata,0,mode);
2670                         data_size = 4;
2671                         break;
2672
2673                 case SMB_FILE_ALIGNMENT_INFORMATION:
2674                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2675                         SIVAL(pdata,0,0); /* No alignment needed. */
2676                         data_size = 4;
2677                         break;
2678
2679 #if 0
2680                 /*
2681                  * NT4 server just returns "invalid query" to this - if we try to answer
2682                  * it then NTws gets a BSOD! (tridge).
2683                  * W2K seems to want this. JRA.
2684                  */
2685                 case SMB_QUERY_FILE_STREAM_INFO:
2686 #endif
2687                 case SMB_FILE_STREAM_INFORMATION:
2688                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2689                         if (mode & aDIR) {
2690                                 data_size = 0;
2691                         } else {
2692                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2693                                 SIVAL(pdata,0,0); /* ??? */
2694                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2695                                 SOFF_T(pdata,8,file_size);
2696                                 SIVAL(pdata,16,allocation_size);
2697                                 SIVAL(pdata,20,0); /* ??? */
2698                                 data_size = 24 + byte_len;
2699                         }
2700                         break;
2701
2702                 case SMB_QUERY_COMPRESSION_INFO:
2703                 case SMB_FILE_COMPRESSION_INFORMATION:
2704                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2705                         SOFF_T(pdata,0,file_size);
2706                         SIVAL(pdata,8,0); /* ??? */
2707                         SIVAL(pdata,12,0); /* ??? */
2708                         data_size = 16;
2709                         break;
2710
2711                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2712                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2713                         put_long_date(pdata,c_time);
2714                         put_long_date(pdata+8,sbuf.st_atime);
2715                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2716                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2717                         SIVAL(pdata,32,allocation_size);
2718                         SOFF_T(pdata,40,file_size);
2719                         SIVAL(pdata,48,mode);
2720                         SIVAL(pdata,52,0); /* ??? */
2721                         data_size = 56;
2722                         break;
2723
2724                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2725                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2726                         SIVAL(pdata,0,mode);
2727                         SIVAL(pdata,4,0);
2728                         data_size = 8;
2729                         break;
2730
2731                 /*
2732                  * CIFS UNIX Extensions.
2733                  */
2734
2735                 case SMB_QUERY_FILE_UNIX_BASIC:
2736
2737                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2738                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2739
2740                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
2741                         pdata += 8;
2742
2743                         SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2744                         pdata += 8;
2745
2746                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
2747                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
2748                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
2749                         pdata += 24;
2750
2751                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
2752                         SIVAL(pdata,4,0);
2753                         pdata += 8;
2754
2755                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
2756                         SIVAL(pdata,4,0);
2757                         pdata += 8;
2758
2759                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2760                         pdata += 4;
2761
2762                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
2763                         SIVAL(pdata,4,0);
2764                         pdata += 8;
2765
2766                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
2767                         SIVAL(pdata,4,0);
2768                         pdata += 8;
2769
2770                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
2771                         pdata += 8;
2772                                 
2773                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
2774                         SIVAL(pdata,4,0);
2775                         pdata += 8;
2776
2777                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
2778                         SIVAL(pdata,4,0);
2779                         pdata += 8+1;
2780                         data_size = PTR_DIFF(pdata,(*ppdata));
2781
2782                         {
2783                                 int i;
2784                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2785
2786                                 for (i=0; i<100; i++)
2787                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2788                                 DEBUG(4,("\n"));
2789                         }
2790
2791                         break;
2792
2793                 case SMB_QUERY_FILE_UNIX_LINK:
2794                         {
2795                                 pstring buffer;
2796
2797                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2798 #ifdef S_ISLNK
2799                                 if(!S_ISLNK(sbuf.st_mode))
2800                                         return(UNIXERROR(ERRSRV,ERRbadlink));
2801 #else
2802                                 return(UNIXERROR(ERRDOS,ERRbadlink));
2803 #endif
2804                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
2805                                 if (len == -1)
2806                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2807                                 buffer[len] = 0;
2808                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2809                                 pdata += len;
2810                                 data_size = PTR_DIFF(pdata,(*ppdata));
2811
2812                                 break;
2813                         }
2814
2815                 default:
2816                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2817         }
2818
2819         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2820
2821         return(-1);
2822 }
2823
2824 /****************************************************************************
2825  Deal with the internal needs of setting the delete on close flag. Note that
2826  as the tdb locking is recursive, it is safe to call this from within 
2827  open_file_shared. JRA.
2828 ****************************************************************************/
2829
2830 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2831 {
2832         /*
2833          * Only allow delete on close for writable shares.
2834          */
2835
2836         if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2837                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2838                                 fsp->fsp_name ));
2839                                 return NT_STATUS_ACCESS_DENIED;
2840         }
2841         /*
2842          * Only allow delete on close for files/directories opened with delete intent.
2843          */
2844
2845         if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2846                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2847                                 fsp->fsp_name ));
2848                                 return NT_STATUS_ACCESS_DENIED;
2849         }
2850
2851         if(fsp->is_directory) {
2852                 fsp->directory_delete_on_close = delete_on_close;
2853                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2854                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2855         } else {
2856                 fsp->delete_on_close = delete_on_close;
2857                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2858                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2859         }
2860
2861         return NT_STATUS_OK;
2862 }
2863
2864 /****************************************************************************
2865  Sets the delete on close flag over all share modes on this file.
2866  Modify the share mode entry for all files open
2867  on this device and inode to tell other smbds we have
2868  changed the delete on close flag. This will be noticed
2869  in the close code, the last closer will delete the file
2870  if flag is set.
2871 ****************************************************************************/
2872
2873 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2874 {
2875         DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2876                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2877
2878         if (fsp->is_directory || fsp->is_stat)
2879                 return NT_STATUS_OK;
2880
2881         if (lock_share_entry_fsp(fsp) == False)
2882                 return NT_STATUS_ACCESS_DENIED;
2883
2884         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2885                 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2886                         fsp->fsp_name ));
2887                 unlock_share_entry_fsp(fsp);
2888                 return NT_STATUS_ACCESS_DENIED;
2889         }
2890
2891         unlock_share_entry_fsp(fsp);
2892         return NT_STATUS_OK;
2893 }
2894
2895 /****************************************************************************
2896  Set a hard link (called by UNIX extensions and by NT rename with HARD link
2897  code.
2898 ****************************************************************************/
2899
2900 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2901 {
2902         BOOL bad_path_oldname = False;
2903         BOOL bad_path_newname = False;
2904         SMB_STRUCT_STAT sbuf1, sbuf2;
2905         pstring last_component_oldname;
2906         pstring last_component_newname;
2907         NTSTATUS status = NT_STATUS_OK;
2908
2909         ZERO_STRUCT(sbuf1);
2910         ZERO_STRUCT(sbuf2);
2911
2912         /* No wildcards. */
2913         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2914                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2915         }
2916
2917         unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2918         if (bad_path_oldname) {
2919                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2920         }
2921
2922         /* Quick check for "." and ".." */
2923         if (last_component_oldname[0] == '.') {
2924                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2925                         return NT_STATUS_OBJECT_NAME_INVALID;
2926                 }
2927         }
2928
2929         /* source must already exist. */
2930         if (!VALID_STAT(sbuf1)) {
2931                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2932         }
2933
2934         if (!check_name(oldname,conn)) {
2935                 return NT_STATUS_ACCESS_DENIED;
2936         }
2937
2938         unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2939         if (bad_path_newname) {
2940                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2941         }
2942
2943         /* Quick check for "." and ".." */
2944         if (last_component_newname[0] == '.') {
2945                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2946                         return NT_STATUS_OBJECT_NAME_INVALID;
2947                 }
2948         }
2949
2950         /* Disallow if newname already exists. */
2951         if (VALID_STAT(sbuf2)) {
2952                 return NT_STATUS_OBJECT_NAME_COLLISION;
2953         }
2954
2955         if (!check_name(newname,conn)) {
2956                 return NT_STATUS_ACCESS_DENIED;
2957         }
2958
2959         /* No links from a directory. */
2960         if (S_ISDIR(sbuf1.st_mode)) {
2961                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2962         }
2963
2964         /* Ensure this is within the share. */
2965         if (!reduce_name(conn, oldname) != 0)
2966                 return NT_STATUS_ACCESS_DENIED;
2967
2968         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
2969
2970         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
2971                 status = map_nt_error_from_unix(errno);
2972                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
2973                                 nt_errstr(status), newname, oldname));
2974         }
2975
2976         return status;
2977 }
2978
2979 /****************************************************************************
2980  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2981 ****************************************************************************/
2982
2983 static int call_trans2setfilepathinfo(connection_struct *conn,
2984                                         char *inbuf, char *outbuf, int length, int bufsize,
2985                                         char **pparams, int total_params, char **ppdata, int total_data)
2986 {
2987         char *params = *pparams;
2988         char *pdata = *ppdata;
2989         uint16 tran_call = SVAL(inbuf, smb_setup0);
2990         uint16 info_level;
2991         int dosmode=0;
2992         SMB_OFF_T size=0;
2993         struct utimbuf tvs;
2994         SMB_STRUCT_STAT sbuf;
2995         pstring fname;
2996         int fd = -1;
2997         BOOL bad_path = False;
2998         files_struct *fsp = NULL;
2999         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3000         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3001         mode_t unixmode = 0;
3002         NTSTATUS status = NT_STATUS_OK;
3003
3004         if (!params)
3005                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3006
3007         ZERO_STRUCT(sbuf);
3008
3009         if (tran_call == TRANSACT2_SETFILEINFO) {
3010                 if (total_params < 4)
3011                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3012
3013                 fsp = file_fsp(params,0);
3014                 info_level = SVAL(params,2);    
3015
3016                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3017                         /*
3018                          * This is actually a SETFILEINFO on a directory
3019                          * handle (returned from an NT SMB). NT5.0 seems
3020                          * to do this call. JRA.
3021                          */
3022                         pstrcpy(fname, fsp->fsp_name);
3023                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3024                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3025                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3026                         }
3027                 } else if (fsp && fsp->print_file) {
3028                         /*
3029                          * Doing a DELETE_ON_CLOSE should cancel a print job.
3030                          */
3031                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3032                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3033
3034                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3035         
3036                                 SSVAL(params,0,0);
3037                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3038                                 return(-1);
3039                         } else
3040                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3041             } else {
3042                         /*
3043                          * Original code - this is an open file.
3044                          */
3045                         CHECK_FSP(fsp,conn);
3046
3047                         pstrcpy(fname, fsp->fsp_name);
3048                         fd = fsp->fd;
3049
3050                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3051                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3052                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3053                         }
3054                 }
3055         } else {
3056                 /* set path info */
3057                 if (total_params < 6)
3058                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3059
3060                 info_level = SVAL(params,0);    
3061                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3062                 if (!NT_STATUS_IS_OK(status)) {
3063                         return ERROR_NT(status);
3064                 }
3065                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3066                 if (bad_path) {
3067                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3068                 }
3069
3070                 /*
3071                  * For CIFS UNIX extensions the target name may not exist.
3072                  */
3073
3074                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3075                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3076                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3077                 }    
3078
3079                 if(!check_name(fname, conn)) {
3080                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3081                 }
3082
3083         }
3084
3085         if (!CAN_WRITE(conn))
3086                 return ERROR_DOS(ERRSRV,ERRaccess);
3087
3088         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3089                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3090
3091         if (VALID_STAT(sbuf))
3092                 unixmode = sbuf.st_mode;
3093
3094         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3095                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3096
3097         /* Realloc the parameter and data sizes */
3098         params = Realloc(*pparams,2);
3099         if(params == NULL)
3100                 return ERROR_DOS(ERRDOS,ERRnomem);
3101         *pparams = params;
3102
3103         SSVAL(params,0,0);
3104
3105         if (fsp) {
3106                 /* the pending modtime overrides the current modtime */
3107                 sbuf.st_mtime = fsp->pending_modtime;
3108         }
3109
3110         size = get_file_size(sbuf);
3111         tvs.modtime = sbuf.st_mtime;
3112         tvs.actime = sbuf.st_atime;
3113         dosmode = dos_mode(conn,fname,&sbuf);
3114         unixmode = sbuf.st_mode;
3115
3116         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3117         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3118
3119         switch (info_level) {
3120                 case SMB_INFO_STANDARD:
3121                 {
3122                         if (total_data < 12)
3123                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3124
3125                         /* access time */
3126                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3127                         /* write time */
3128                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3129                         break;
3130                 }
3131
3132                 case SMB_INFO_SET_EA:
3133                         status = set_ea(conn, fsp, fname, pdata, total_data);
3134                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3135                                 return ERROR_NT(status);
3136                         break;
3137
3138                 /* XXXX um, i don't think this is right.
3139                         it's also not in the cifs6.txt spec.
3140                 */
3141                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3142                         if (total_data < 28)
3143                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3144
3145                         tvs.actime = make_unix_date2(pdata+8);
3146                         tvs.modtime = make_unix_date2(pdata+12);
3147                         size = IVAL(pdata,16);
3148                         dosmode = IVAL(pdata,24);
3149                         break;
3150
3151                 /* XXXX nor this.  not in cifs6.txt, either. */
3152                 case SMB_INFO_QUERY_ALL_EAS:
3153                         if (total_data < 28)
3154                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3155
3156                         tvs.actime = make_unix_date2(pdata+8);
3157                         tvs.modtime = make_unix_date2(pdata+12);
3158                         size = IVAL(pdata,16);
3159                         dosmode = IVAL(pdata,24);
3160                         break;
3161
3162                 case SMB_SET_FILE_BASIC_INFO:
3163                 case SMB_FILE_BASIC_INFORMATION:
3164                 {
3165                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3166                         time_t write_time;
3167                         time_t changed_time;
3168
3169                         if (total_data < 36)
3170                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3171
3172                         /* Ignore create time at offset pdata. */
3173
3174                         /* access time */
3175                         tvs.actime = interpret_long_date(pdata+8);
3176
3177                         write_time = interpret_long_date(pdata+16);
3178                         changed_time = interpret_long_date(pdata+24);
3179
3180                         tvs.modtime = MIN(write_time, changed_time);
3181
3182                         if (write_time > tvs.modtime && write_time != 0xffffffff) {
3183                                 tvs.modtime = write_time;
3184                         }
3185                         /* Prefer a defined time to an undefined one. */
3186                         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3187                                 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3188                                         ? changed_time : write_time);
3189
3190                         /* attributes */
3191                         dosmode = IVAL(pdata,32);
3192                         break;
3193                 }
3194
3195                 case SMB_FILE_ALLOCATION_INFORMATION:
3196                 case SMB_SET_FILE_ALLOCATION_INFO:
3197                 {
3198                         int ret = -1;
3199                         SMB_BIG_UINT allocation_size;
3200
3201                         if (total_data < 8)
3202                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3203
3204                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3205 #ifdef LARGE_SMB_OFF_T
3206                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3207 #else /* LARGE_SMB_OFF_T */
3208                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3209                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3210 #endif /* LARGE_SMB_OFF_T */
3211                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3212                                         fname, (double)allocation_size ));
3213
3214                         if (allocation_size)
3215                                 allocation_size = smb_roundup(allocation_size);
3216
3217                         if(allocation_size != get_file_size(sbuf)) {
3218                                 SMB_STRUCT_STAT new_sbuf;
3219  
3220                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3221                                         fname, (double)allocation_size ));
3222  
3223                                 if (fd == -1) {
3224                                         files_struct *new_fsp = NULL;
3225                                         int access_mode = 0;
3226                                         int action = 0;
3227  
3228                                         if(global_oplock_break) {
3229                                                 /* Queue this file modify as we are the process of an oplock break.  */
3230  
3231                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3232                                                 DEBUGADD(2,( "in oplock break state.\n"));
3233  
3234                                                 push_oplock_pending_smb_message(inbuf, length);
3235                                                 return -1;
3236                                         }
3237  
3238                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3239                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
3240                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3241                                                                         FILE_ATTRIBUTE_NORMAL,
3242                                                                         INTERNAL_OPEN_ONLY, &access_mode, &action);
3243  
3244                                         if (new_fsp == NULL)
3245                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3246                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
3247                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3248                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3249                                                                         new_fsp->fnum, strerror(errno)));
3250                                                 ret = -1;
3251                                         }
3252                                         close_file(new_fsp,True);
3253                                 } else {
3254                                         ret = vfs_allocate_file_space(fsp, allocation_size);
3255                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3256                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3257                                                                         fsp->fnum, strerror(errno)));
3258                                                 ret = -1;
3259                                         }
3260           &nbs