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