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