Fixed delete on close bug. Added core dump code to winbindd.
[import/samba-cvsimport.git] / source / smbd / trans2.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB transaction2 handling
5    Copyright (C) Jeremy Allison 1994-2001
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 BOOL case_sensitive;
28 extern int smb_read_error;
29 extern fstring local_machine;
30 extern int global_oplock_break;
31 extern uint32 global_client_caps;
32 extern pstring global_myname;
33
34 /****************************************************************************
35   Send the required number of replies back.
36   We assume all fields other than the data fields are
37   set correctly for the type of call.
38   HACK ! Always assumes smb_setup field is zero.
39 ****************************************************************************/
40
41 static int send_trans2_replies(char *outbuf, int bufsize, char *params, 
42                                int paramsize, char *pdata, int datasize)
43 {
44   /* As we are using a protocol > LANMAN1 then the max_send
45      variable must have been set in the sessetupX call.
46      This takes precedence over the max_xmit field in the
47      global struct. These different max_xmit variables should
48      be merged as this is now too confusing */
49
50   extern int max_send;
51   int data_to_send = datasize;
52   int params_to_send = paramsize;
53   int useable_space;
54   char *pp = params;
55   char *pd = pdata;
56   int params_sent_thistime, data_sent_thistime, total_sent_thistime;
57   int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
58   int data_alignment_offset = 0;
59
60   /* Initially set the wcnt area to be 10 - this is true for all
61      trans2 replies */
62   set_message(outbuf,10,0,True);
63
64   /* If there genuinely are no parameters or data to send just send
65      the empty packet */
66   if(params_to_send == 0 && data_to_send == 0)
67   {
68     if (!send_smb(smbd_server_fd(),outbuf))
69       exit_server("send_trans2_replies: send_smb failed.");
70     return 0;
71   }
72
73   /* When sending params and data ensure that both are nicely aligned */
74   /* Only do this alignment when there is also data to send - else
75      can cause NT redirector problems. */
76   if (((params_to_send % 4) != 0) && (data_to_send != 0))
77     data_alignment_offset = 4 - (params_to_send % 4);
78
79   /* Space is bufsize minus Netbios over TCP header minus SMB header */
80   /* The alignment_offset is to align the param bytes on an even byte
81      boundary. NT 4.0 Beta needs this to work correctly. */
82   useable_space = bufsize - ((smb_buf(outbuf)+
83                     alignment_offset+data_alignment_offset) - 
84                     outbuf);
85
86   /* useable_space can never be more than max_send minus the
87      alignment offset. */
88   useable_space = MIN(useable_space, 
89                       max_send - (alignment_offset+data_alignment_offset));
90
91
92   while (params_to_send || data_to_send)
93   {
94     /* Calculate whether we will totally or partially fill this packet */
95     total_sent_thistime = params_to_send + data_to_send + 
96                             alignment_offset + data_alignment_offset;
97     /* We can never send more than useable_space */
98     /*
99      * Note that 'useable_space' does not include the alignment offsets,
100      * but we must include the alignment offsets in the calculation of
101      * the length of the data we send over the wire, as the alignment offsets
102      * are sent here. Fix from Marc_Jacobsen@hp.com.
103      */
104     total_sent_thistime = MIN(total_sent_thistime, useable_space+
105                                 alignment_offset + data_alignment_offset);
106
107     set_message(outbuf, 10, total_sent_thistime, True);
108
109     /* Set total params and data to be sent */
110     SSVAL(outbuf,smb_tprcnt,paramsize);
111     SSVAL(outbuf,smb_tdrcnt,datasize);
112
113     /* Calculate how many parameters and data we can fit into
114        this packet. Parameters get precedence */
115
116     params_sent_thistime = MIN(params_to_send,useable_space);
117     data_sent_thistime = useable_space - params_sent_thistime;
118     data_sent_thistime = MIN(data_sent_thistime,data_to_send);
119
120     SSVAL(outbuf,smb_prcnt, params_sent_thistime);
121
122     /* smb_proff is the offset from the start of the SMB header to the
123        parameter bytes, however the first 4 bytes of outbuf are
124        the Netbios over TCP header. Thus use smb_base() to subtract
125        them from the calculation */
126
127     SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
128
129     if(params_sent_thistime == 0)
130       SSVAL(outbuf,smb_prdisp,0);
131     else
132       /* Absolute displacement of param bytes sent in this packet */
133       SSVAL(outbuf,smb_prdisp,pp - params);
134
135     SSVAL(outbuf,smb_drcnt, data_sent_thistime);
136     if(data_sent_thistime == 0)
137     {
138       SSVAL(outbuf,smb_droff,0);
139       SSVAL(outbuf,smb_drdisp, 0);
140     }
141     else
142     {
143       /* The offset of the data bytes is the offset of the
144          parameter bytes plus the number of parameters being sent this time */
145       SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
146             smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
147       SSVAL(outbuf,smb_drdisp, pd - pdata);
148     }
149
150     /* Copy the param bytes into the packet */
151     if(params_sent_thistime)
152       memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
153     /* Copy in the data bytes */
154     if(data_sent_thistime)
155       memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
156              data_alignment_offset,pd,data_sent_thistime);
157
158     DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
159           params_sent_thistime, data_sent_thistime, useable_space));
160     DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
161           params_to_send, data_to_send, paramsize, datasize));
162
163     /* Send the packet */
164     if (!send_smb(smbd_server_fd(),outbuf))
165                 exit_server("send_trans2_replies: send_smb failed.");
166
167     pp += params_sent_thistime;
168     pd += data_sent_thistime;
169
170     params_to_send -= params_sent_thistime;
171     data_to_send -= data_sent_thistime;
172
173     /* Sanity check */
174     if(params_to_send < 0 || data_to_send < 0)
175     {
176       DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
177             params_to_send, data_to_send));
178       return -1;
179     }
180   }
181
182   return 0;
183 }
184
185 /****************************************************************************
186  Reply to a TRANSACT2_OPEN.
187 ****************************************************************************/
188
189 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, 
190                            int bufsize,  
191                            char **pparams, char **ppdata)
192 {
193   char *params = *pparams;
194   int16 open_mode = SVAL(params, 2);
195   int16 open_attr = SVAL(params,6);
196   BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
197 #if 0
198   BOOL return_additional_info = BITSETW(params,0);
199   int16 open_sattr = SVAL(params, 4);
200   time_t open_time = make_unix_date3(params+8);
201 #endif
202   int16 open_ofun = SVAL(params,12);
203   int32 open_size = IVAL(params,14);
204   char *pname = &params[28];
205   pstring fname;
206   mode_t unixmode;
207   SMB_OFF_T size=0;
208   int fmode=0,mtime=0,rmode;
209   SMB_INO_T inode = 0;
210   SMB_STRUCT_STAT sbuf;
211   int smb_action = 0;
212   BOOL bad_path = False;
213   files_struct *fsp;
214
215   srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
216
217   DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
218            fname,open_mode, open_attr, open_ofun, open_size));
219
220   if (IS_IPC(conn)) {
221                 return(ERROR_DOS(ERRSRV,ERRaccess));
222   }
223
224   /* XXXX we need to handle passed times, sattr and flags */
225
226   unix_convert(fname,conn,0,&bad_path,&sbuf);
227     
228   if (!check_name(fname,conn))
229   {
230     if((errno == ENOENT) && bad_path)
231     {
232       unix_ERR_class = ERRDOS;
233       unix_ERR_code = ERRbadpath;
234     }
235     return(UNIXERROR(ERRDOS,ERRnoaccess));
236   }
237
238   unixmode = unix_mode(conn,open_attr | aARCH, fname);
239       
240   fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
241                    oplock_request, &rmode,&smb_action);
242       
243   if (!fsp)
244   {
245     if((errno == ENOENT) && bad_path)
246     {
247       unix_ERR_class = ERRDOS;
248       unix_ERR_code = ERRbadpath;
249     }
250     return(UNIXERROR(ERRDOS,ERRnoaccess));
251   }
252
253   size = sbuf.st_size;
254   fmode = dos_mode(conn,fname,&sbuf);
255   mtime = sbuf.st_mtime;
256   inode = sbuf.st_ino;
257   if (fmode & aDIR) {
258     close_file(fsp,False);
259     return(ERROR_DOS(ERRDOS,ERRnoaccess));
260   }
261
262   /* Realloc the size of parameters and data we will return */
263   params        = Realloc(*pparams, 28);
264   if( params == NULL ) {
265     return(ERROR_DOS(ERRDOS,ERRnomem));
266   }
267   *pparams      = params;
268
269   memset((char *)params,'\0',28);
270   SSVAL(params,0,fsp->fnum);
271   SSVAL(params,2,fmode);
272   put_dos_date2(params,4, mtime);
273   SIVAL(params,8, (uint32)size);
274   SSVAL(params,12,rmode);
275
276   if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
277     smb_action |= EXTENDED_OPLOCK_GRANTED;
278   }
279
280   SSVAL(params,18,smb_action);
281   /*
282    * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
283    */
284   SIVAL(params,20,inode);
285  
286   /* Send the required number of replies */
287   send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
288
289   return -1;
290 }
291
292 /*********************************************************
293  Routine to check if a given string matches exactly.
294  as a special case a mask of "." does NOT match. That
295  is required for correct wildcard semantics
296  Case can be significant or not.
297 **********************************************************/
298
299 static BOOL exact_match(char *str,char *mask, BOOL case_sig) 
300 {
301         if (mask[0] == '.' && mask[1] == 0)
302                 return False;
303         if (case_sig)   
304                 return strcmp(str,mask)==0;
305         return strcasecmp(str,mask) == 0;
306 }
307
308 /****************************************************************************
309  Get a level dependent lanman2 dir entry.
310 ****************************************************************************/
311
312 static BOOL get_lanman2_dir_entry(connection_struct *conn,
313                                   void *inbuf, void *outbuf,
314                                  char *path_mask,int dirtype,int info_level,
315                                  int requires_resume_key,
316                                  BOOL dont_descend,char **ppdata, 
317                                  char *base_data, int space_remaining, 
318                                  BOOL *out_of_space, BOOL *got_exact_match,
319                                  int *last_name_off)
320 {
321         char *dname;
322         BOOL found = False;
323         SMB_STRUCT_STAT sbuf;
324         pstring mask;
325         pstring pathreal;
326         pstring fname;
327         char *p, *q, *pdata = *ppdata;
328         uint32 reskey=0;
329         int prev_dirpos=0;
330         int mode=0;
331         SMB_OFF_T size = 0;
332         SMB_OFF_T allocation_size = 0;
333         uint32 len;
334         time_t mdate=0, adate=0, cdate=0;
335         char *nameptr;
336         BOOL was_8_3;
337         int nt_extmode; /* Used for NT connections instead of mode */
338         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
339
340         *fname = 0;
341         *out_of_space = False;
342         *got_exact_match = False;
343
344         if (!conn->dirptr)
345                 return(False);
346
347         p = strrchr_m(path_mask,'/');
348         if(p != NULL) {
349                 if(p[1] == '\0')
350                         pstrcpy(mask,"*.*");
351                 else
352                         pstrcpy(mask, p+1);
353         } else
354                 pstrcpy(mask, path_mask);
355
356         while (!found) {
357                 BOOL got_match;
358
359                 /* Needed if we run out of space */
360                 prev_dirpos = TellDir(conn->dirptr);
361                 dname = ReadDirName(conn->dirptr);
362
363                 /*
364                  * Due to bugs in NT client redirectors we are not using
365                  * resume keys any more - set them to zero.
366                  * Check out the related comments in findfirst/findnext.
367                  * JRA.
368                  */
369
370                 reskey = 0;
371
372                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
373                         (long)conn->dirptr,TellDir(conn->dirptr)));
374       
375                 if (!dname) 
376                         return(False);
377
378                 pstrcpy(fname,dname);      
379
380                 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
381                         got_match = mask_match(fname, mask, case_sensitive);
382
383                 if(!got_match && !is_8_3(fname, False)) {
384
385                         /*
386                          * It turns out that NT matches wildcards against
387                          * both long *and* short names. This may explain some
388                          * of the wildcard wierdness from old DOS clients
389                          * that some people have been seeing.... JRA.
390                          */
391
392                         pstring newname;
393                         pstrcpy( newname, fname);
394                         name_map_mangle( newname, True, False, SNUM(conn));
395                         if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
396                                 got_match = mask_match(newname, mask, case_sensitive);
397                 }
398
399                 if(got_match) {
400                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
401                         if (dont_descend && !isdots)
402                                 continue;
403           
404                         pstrcpy(pathreal,conn->dirpath);
405                         if(needslash)
406                                 pstrcat(pathreal,"/");
407                         pstrcat(pathreal,dname);
408
409                         if (vfs_stat(conn,pathreal,&sbuf) != 0) {
410                                 /* Needed to show the msdfs symlinks as directories */
411                                 if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) 
412                                                 || !is_msdfs_link(conn, pathreal)) {
413                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
414                                                         pathreal,strerror(errno)));
415                                         continue;
416                                 } else {
417                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n",
418                                                         pathreal));
419                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
420                                 }
421                         }
422
423                         mode = dos_mode(conn,pathreal,&sbuf);
424
425                         if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
426                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
427                                 continue;
428                         }
429
430                         size = sbuf.st_size;
431                         allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
432                         mdate = sbuf.st_mtime;
433                         adate = sbuf.st_atime;
434                         cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
435
436                         if (lp_dos_filetime_resolution(SNUM(conn))) {
437                                 cdate &= ~1;
438                                 mdate &= ~1;
439                                 adate &= ~1;
440                         }
441
442                         if(mode & aDIR)
443                                 size = 0;
444
445                         DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
446           
447                         found = True;
448                 }
449         }
450
451         name_map_mangle(fname,False,True,SNUM(conn));
452
453         p = pdata;
454         nameptr = p;
455
456         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
457
458         switch (info_level) {
459                 case 1:
460                         if(requires_resume_key) {
461                                 SIVAL(p,0,reskey);
462                                 p += 4;
463                         }
464                         put_dos_date2(p,l1_fdateCreation,cdate);
465                         put_dos_date2(p,l1_fdateLastAccess,adate);
466                         put_dos_date2(p,l1_fdateLastWrite,mdate);
467                         SIVAL(p,l1_cbFile,(uint32)size);
468                         SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
469                         SSVAL(p,l1_attrFile,mode);
470                         p += l1_achName;
471                         nameptr = p;
472                         p += align_string(outbuf, p, 0);
473                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
474                         SCVAL(nameptr, -1, len);
475                         p += len;
476                         break;
477
478                 case 2:
479                         if(requires_resume_key) {
480                                 SIVAL(p,0,reskey);
481                                 p += 4;
482                         }
483                         put_dos_date2(p,l2_fdateCreation,cdate);
484                         put_dos_date2(p,l2_fdateLastAccess,adate);
485                         put_dos_date2(p,l2_fdateLastWrite,mdate);
486                         SIVAL(p,l2_cbFile,(uint32)size);
487                         SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
488                         SSVAL(p,l2_attrFile,mode);
489                         SIVAL(p,l2_cbList,0); /* No extended attributes */
490                         p += l2_achName;
491                         nameptr = p;
492                         len = srvstr_push(outbuf, p, fname, -1, STR_NOALIGN);
493                         SCVAL(p, -1, len);
494                         p += len;
495                         *p++ = 0; /* craig from unisys pointed out we need this */
496                         break;
497
498                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
499                         was_8_3 = is_8_3(fname, True);
500                         p += 4;
501                         SIVAL(p,0,reskey); p += 4;
502                         put_long_date(p,cdate); p += 8;
503                         put_long_date(p,adate); p += 8;
504                         put_long_date(p,mdate); p += 8;
505                         put_long_date(p,mdate); p += 8;
506                         SOFF_T(p,0,size);
507                         SOFF_T(p,8,allocation_size);
508                         p += 16;
509                         SIVAL(p,0,nt_extmode); p += 4;
510                         q = p; p += 4;
511                         SIVAL(p,0,0); p += 4;
512                         if (!was_8_3) {
513                                 pstring mangled_name;
514                                 pstrcpy(mangled_name, fname);
515                                 name_map_mangle(mangled_name,True,True,SNUM(conn));
516                                 mangled_name[12] = 0;
517                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER);
518                                 SSVAL(p, 0, len);
519                         } else {
520                                 SSVAL(p,0,0);
521                                 *(p+2) = 0;
522                         }
523                         p += 2 + 24;
524                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
525                         SIVAL(q,0,len);
526                         p += len;
527                         len = PTR_DIFF(p, pdata);
528                         len = (len + 3) & ~3;
529                         SIVAL(pdata,0,len);
530                         p = pdata + len;
531                         break;
532
533                 case SMB_FIND_FILE_DIRECTORY_INFO:
534                         p += 4;
535                         SIVAL(p,0,reskey); p += 4;
536                         put_long_date(p,cdate); p += 8;
537                         put_long_date(p,adate); p += 8;
538                         put_long_date(p,mdate); p += 8;
539                         put_long_date(p,mdate); p += 8;
540                         SOFF_T(p,0,size);
541                         SOFF_T(p,8,allocation_size);
542                         p += 16;
543                         SIVAL(p,0,nt_extmode); p += 4;
544                         p += 4;
545                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
546                         SIVAL(p, -4, len);
547                         p += len;
548                         len = PTR_DIFF(p, pdata);
549                         len = (len + 3) & ~3;
550                         SIVAL(pdata,0,len);
551                         p = pdata + len;
552                         break;
553       
554                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
555                         p += 4;
556                         SIVAL(p,0,reskey); p += 4;
557                         put_long_date(p,cdate); p += 8;
558                         put_long_date(p,adate); p += 8;
559                         put_long_date(p,mdate); p += 8;
560                         put_long_date(p,mdate); p += 8;
561                         SOFF_T(p,0,size); 
562                         SOFF_T(p,8,allocation_size);
563                         p += 16;
564                         SIVAL(p,0,nt_extmode); p += 4;
565                         p += 4;
566                         SIVAL(p,0,0); p += 4;
567
568                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
569                         SIVAL(p, -4, len);
570                         p += len;
571
572                         len = PTR_DIFF(p, pdata);
573                         len = (len + 3) & ~3;
574                         SIVAL(pdata,0,len);
575                         p = pdata + len;
576                         break;
577
578                 case SMB_FIND_FILE_NAMES_INFO:
579                         p += 4;
580                         SIVAL(p,0,reskey); p += 4;
581                         p += 4;
582                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
583                         SIVAL(p, -4, len);
584                         p += len;
585                         len = PTR_DIFF(p, pdata);
586                         len = (len + 3) & ~3;
587                         SIVAL(pdata,0,len);
588                         p = pdata + len;
589                         break;
590
591                 default:      
592                         return(False);
593         }
594
595
596         if (PTR_DIFF(p,pdata) > space_remaining) {
597                 /* Move the dirptr back to prev_dirpos */
598                 SeekDir(conn->dirptr, prev_dirpos);
599                 *out_of_space = True;
600                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
601                 return False; /* Not finished - just out of space */
602         }
603
604         /* Setup the last_filename pointer, as an offset from base_data */
605         *last_name_off = PTR_DIFF(nameptr,base_data);
606         /* Advance the data pointer to the next slot */
607         *ppdata = p;
608
609         return(found);
610 }
611
612 /****************************************************************************
613  Reply to a TRANS2_FINDFIRST.
614 ****************************************************************************/
615
616 static int call_trans2findfirst(connection_struct *conn,
617                                 char *inbuf, char *outbuf, int bufsize,  
618                                 char **pparams, char **ppdata)
619 {
620   /* We must be careful here that we don't return more than the
621      allowed number of data bytes. If this means returning fewer than
622      maxentries then so be it. We assume that the redirector has
623      enough room for the fixed number of parameter bytes it has
624      requested. */
625   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
626   char *params = *pparams;
627   char *pdata = *ppdata;
628   int dirtype = SVAL(params,0);
629   int maxentries = SVAL(params,2);
630   BOOL close_after_first = BITSETW(params+4,0);
631   BOOL close_if_end = BITSETW(params+4,1);
632   BOOL requires_resume_key = BITSETW(params+4,2);
633   int info_level = SVAL(params,6);
634   pstring directory;
635   pstring mask;
636   char *p, *wcard;
637   int last_name_off=0;
638   int dptr_num = -1;
639   int numentries = 0;
640   int i;
641   BOOL finished = False;
642   BOOL dont_descend = False;
643   BOOL out_of_space = False;
644   int space_remaining;
645   BOOL bad_path = False;
646   SMB_STRUCT_STAT sbuf;
647
648   *directory = *mask = 0;
649
650   DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
651            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
652            info_level, max_data_bytes));
653   
654   switch (info_level) 
655     {
656     case 1:
657     case 2:
658     case 3:
659     case 4:
660     case SMB_FIND_FILE_DIRECTORY_INFO:
661     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
662     case SMB_FIND_FILE_NAMES_INFO:
663     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
664       break;
665     default:
666       return(ERROR_DOS(ERRDOS,ERRunknownlevel));
667     }
668
669   srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
670
671   RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
672
673   unix_convert(directory,conn,0,&bad_path,&sbuf);
674   if(!check_name(directory,conn)) {
675     if((errno == ENOENT) && bad_path)
676     {
677       unix_ERR_class = ERRDOS;
678       unix_ERR_code = ERRbadpath;
679     }
680
681 #if 0
682     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
683     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
684        (get_remote_arch() == RA_WINNT))
685     {
686       unix_ERR_class = ERRDOS;
687       unix_ERR_code = ERRbaddirectory;
688     }
689 #endif 
690
691     return(UNIXERROR(ERRDOS,ERRbadpath));
692   }
693
694   p = strrchr_m(directory,'/');
695   if(p == NULL) {
696     pstrcpy(mask,directory);
697     pstrcpy(directory,"./");
698   } else {
699     pstrcpy(mask,p+1);
700     *p = 0;
701   }
702
703   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
704
705   pdata = Realloc(*ppdata, max_data_bytes + 1024);
706   if( pdata == NULL ) {
707     return(ERROR_DOS(ERRDOS,ERRnomem));
708   }
709   *ppdata       = pdata;
710   memset((char *)pdata,'\0',max_data_bytes + 1024);
711
712   /* Realloc the params space */
713   params = Realloc(*pparams, 10);
714   if (params == NULL) {
715     return ERROR_DOS(ERRDOS,ERRnomem);
716   }
717   *pparams      = params;
718
719   dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
720   if (dptr_num < 0)
721     return(UNIXERROR(ERRDOS,ERRbadfile));
722
723   /* Save the wildcard match and attribs we are using on this directory - 
724      needed as lanman2 assumes these are being saved between calls */
725
726   if(!(wcard = strdup(mask))) {
727     dptr_close(&dptr_num);
728     return ERROR_DOS(ERRDOS,ERRnomem);
729   }
730
731   dptr_set_wcard(dptr_num, wcard);
732   dptr_set_attr(dptr_num, dirtype);
733
734   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
735
736   /* We don't need to check for VOL here as this is returned by 
737      a different TRANS2 call. */
738   
739   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
740            conn->dirpath,lp_dontdescend(SNUM(conn))));
741   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
742     dont_descend = True;
743     
744   p = pdata;
745   space_remaining = max_data_bytes;
746   out_of_space = False;
747
748   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
749   {
750     BOOL got_exact_match = False;
751
752     /* this is a heuristic to avoid seeking the dirptr except when 
753        absolutely necessary. It allows for a filename of about 40 chars */
754     if (space_remaining < DIRLEN_GUESS && numentries > 0)
755     {
756       out_of_space = True;
757       finished = False;
758     }
759     else
760     {
761       finished = !get_lanman2_dir_entry(conn,
762                                         inbuf, outbuf,
763                                         mask,dirtype,info_level,
764                                         requires_resume_key,dont_descend,
765                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
766                                         &last_name_off);
767     }
768
769     if (finished && out_of_space)
770       finished = False;
771
772     if (!finished && !out_of_space)
773       numentries++;
774
775     /*
776      * As an optimisation if we know we aren't looking
777      * for a wildcard name (ie. the name matches the wildcard exactly)
778      * then we can finish on any (first) match.
779      * This speeds up large directory searches. JRA.
780      */
781
782     if(got_exact_match)
783       finished = True;
784
785     space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
786   }
787   
788   /* Check if we can close the dirptr */
789   if(close_after_first || (finished && close_if_end))
790   {
791     DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
792     dptr_close(&dptr_num);
793   }
794
795   /* 
796    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
797    * from observation of NT.
798    */
799
800   if(numentries == 0) {
801           dptr_close(&dptr_num);
802           return ERROR_DOS(ERRDOS,ERRbadfile);
803   }
804
805   /* At this point pdata points to numentries directory entries. */
806
807   /* Set up the return parameter block */
808   SSVAL(params,0,dptr_num);
809   SSVAL(params,2,numentries);
810   SSVAL(params,4,finished);
811   SSVAL(params,6,0); /* Never an EA error */
812   SSVAL(params,8,last_name_off);
813
814   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
815
816   if ((! *directory) && dptr_path(dptr_num))
817     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
818
819   DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
820             smb_fn_name(CVAL(inbuf,smb_com)), 
821             mask, directory, dirtype, numentries ) );
822
823   /* 
824    * Force a name mangle here to ensure that the
825    * mask as an 8.3 name is top of the mangled cache.
826    * The reasons for this are subtle. Don't remove
827    * this code unless you know what you are doing
828    * (see PR#13758). JRA.
829    */
830
831   if(!is_8_3( mask, False))
832     name_map_mangle(mask, True, True, SNUM(conn));
833
834   return(-1);
835 }
836
837 /****************************************************************************
838  Reply to a TRANS2_FINDNEXT.
839 ****************************************************************************/
840
841 static int call_trans2findnext(connection_struct *conn, 
842                                char *inbuf, char *outbuf, 
843                                int length, int bufsize,
844                                char **pparams, char **ppdata)
845 {
846   /* We must be careful here that we don't return more than the
847      allowed number of data bytes. If this means returning fewer than
848      maxentries then so be it. We assume that the redirector has
849      enough room for the fixed number of parameter bytes it has
850      requested. */
851   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
852   char *params = *pparams;
853   char *pdata = *ppdata;
854   int dptr_num = SVAL(params,0);
855   int maxentries = SVAL(params,2);
856   uint16 info_level = SVAL(params,4);
857   uint32 resume_key = IVAL(params,6);
858   BOOL close_after_request = BITSETW(params+10,0);
859   BOOL close_if_end = BITSETW(params+10,1);
860   BOOL requires_resume_key = BITSETW(params+10,2);
861   BOOL continue_bit = BITSETW(params+10,3);
862   pstring resume_name;
863   pstring mask;
864   pstring directory;
865   char *p;
866   uint16 dirtype;
867   int numentries = 0;
868   int i, last_name_off=0;
869   BOOL finished = False;
870   BOOL dont_descend = False;
871   BOOL out_of_space = False;
872   int space_remaining;
873
874   *mask = *directory = *resume_name = 0;
875
876   srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
877
878   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
879 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
880 resume_key = %d resume name = %s continue=%d level = %d\n",
881            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
882            requires_resume_key, resume_key, resume_name, continue_bit, info_level));
883
884   switch (info_level) 
885     {
886     case 1:
887     case 2:
888     case 3:
889     case 4:
890     case SMB_FIND_FILE_DIRECTORY_INFO:
891     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
892     case SMB_FIND_FILE_NAMES_INFO:
893     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
894       break;
895     default:
896       return ERROR_DOS(ERRDOS,ERRunknownlevel);
897     }
898
899   pdata = Realloc( *ppdata, max_data_bytes + 1024);
900   if(pdata == NULL) {
901     return ERROR_DOS(ERRDOS,ERRnomem);
902   }
903   *ppdata       = pdata;
904   memset((char *)pdata,'\0',max_data_bytes + 1024);
905
906   /* Realloc the params space */
907   params = Realloc(*pparams, 6*SIZEOFWORD);
908   if( params == NULL ) {
909     return ERROR_DOS(ERRDOS,ERRnomem);
910   }
911   *pparams      = params;
912
913   /* Check that the dptr is valid */
914   if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
915     return ERROR_DOS(ERRDOS,ERRnofiles);
916
917   string_set(&conn->dirpath,dptr_path(dptr_num));
918
919   /* Get the wildcard mask from the dptr */
920   if((p = dptr_wcard(dptr_num))== NULL) {
921     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
922     return ERROR_DOS(ERRDOS,ERRnofiles);
923   }
924   pstrcpy(mask, p);
925   pstrcpy(directory,conn->dirpath);
926
927   /* Get the attr mask from the dptr */
928   dirtype = dptr_attr(dptr_num);
929
930   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
931            dptr_num, mask, dirtype, 
932            (long)conn->dirptr,
933            TellDir(conn->dirptr)));
934
935   /* We don't need to check for VOL here as this is returned by 
936      a different TRANS2 call. */
937
938   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
939   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
940     dont_descend = True;
941     
942   p = pdata;
943   space_remaining = max_data_bytes;
944   out_of_space = False;
945
946   /* 
947    * Seek to the correct position. We no longer use the resume key but
948    * depend on the last file name instead.
949    */
950   if(requires_resume_key && *resume_name && !continue_bit)
951   {
952     /*
953      * Fix for NT redirector problem triggered by resume key indexes
954      * changing between directory scans. We now return a resume key of 0
955      * and instead look for the filename to continue from (also given
956      * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
957      * findfirst/findnext (as is usual) then the directory pointer
958      * should already be at the correct place. Check this by scanning
959      * backwards looking for an exact (ie. case sensitive) filename match. 
960      * If we get to the beginning of the directory and haven't found it then scan
961      * forwards again looking for a match. JRA.
962      */
963
964     int current_pos, start_pos;
965     char *dname = NULL;
966     void *dirptr = conn->dirptr;
967     start_pos = TellDir(dirptr);
968     for(current_pos = start_pos; current_pos >= 0; current_pos--)
969     {
970       DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
971
972       SeekDir(dirptr, current_pos);
973       dname = ReadDirName(dirptr);
974
975       /*
976        * Remember, name_map_mangle is called by
977        * get_lanman2_dir_entry(), so the resume name
978        * could be mangled. Ensure we do the same
979        * here.
980        */
981
982       if(dname != NULL)
983         name_map_mangle( dname, False, True, SNUM(conn));
984
985       if(dname && strcsequal( resume_name, dname))
986       {
987         SeekDir(dirptr, current_pos+1);
988         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
989         break;
990       }
991     }
992
993     /*
994      * Scan forward from start if not found going backwards.
995      */
996
997     if(current_pos < 0)
998     {
999       DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1000       SeekDir(dirptr, start_pos);
1001       for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
1002       {
1003         /*
1004          * Remember, name_map_mangle is called by
1005          * get_lanman2_dir_entry(), so the resume name
1006          * could be mangled. Ensure we do the same
1007          * here.
1008          */
1009
1010         if(dname != NULL)
1011           name_map_mangle( dname, False, True, SNUM(conn));
1012
1013         if(dname && strcsequal( resume_name, dname))
1014         {
1015           SeekDir(dirptr, current_pos+1);
1016           DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1017           break;
1018         }
1019       } /* end for */
1020     } /* end if current_pos */
1021   } /* end if requires_resume_key && !continue_bit */
1022
1023   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1024   {
1025     BOOL got_exact_match = False;
1026
1027     /* this is a heuristic to avoid seeking the dirptr except when 
1028        absolutely necessary. It allows for a filename of about 40 chars */
1029     if (space_remaining < DIRLEN_GUESS && numentries > 0)
1030     {
1031       out_of_space = True;
1032       finished = False;
1033     }
1034     else
1035     {
1036       finished = !get_lanman2_dir_entry(conn,
1037                                         inbuf, outbuf,
1038                                         mask,dirtype,info_level,
1039                                         requires_resume_key,dont_descend,
1040                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1041                                         &last_name_off);
1042     }
1043
1044     if (finished && out_of_space)
1045       finished = False;
1046
1047     if (!finished && !out_of_space)
1048       numentries++;
1049
1050     /*
1051      * As an optimisation if we know we aren't looking
1052      * for a wildcard name (ie. the name matches the wildcard exactly)
1053      * then we can finish on any (first) match.
1054      * This speeds up large directory searches. JRA.
1055      */
1056
1057     if(got_exact_match)
1058       finished = True;
1059
1060     space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1061   }
1062   
1063   /* Check if we can close the dirptr */
1064   if(close_after_request || (finished && close_if_end))
1065   {
1066     DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1067     dptr_close(&dptr_num); /* This frees up the saved mask */
1068   }
1069
1070
1071   /* Set up the return parameter block */
1072   SSVAL(params,0,numentries);
1073   SSVAL(params,2,finished);
1074   SSVAL(params,4,0); /* Never an EA error */
1075   SSVAL(params,6,last_name_off);
1076
1077   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1078
1079   if ((! *directory) && dptr_path(dptr_num))
1080     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1081
1082   DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1083             smb_fn_name(CVAL(inbuf,smb_com)), 
1084             mask, directory, dirtype, numentries ) );
1085
1086   return(-1);
1087 }
1088
1089 /****************************************************************************
1090  Reply to a TRANS2_QFSINFO (query filesystem info).
1091 ****************************************************************************/
1092
1093 static int call_trans2qfsinfo(connection_struct *conn, 
1094                               char *inbuf, char *outbuf, 
1095                               int length, int bufsize,
1096                               char **pparams, char **ppdata)
1097 {
1098   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1099   char *pdata = *ppdata;
1100   char *params = *pparams;
1101   uint16 info_level = SVAL(params,0);
1102   int data_len, len;
1103   SMB_STRUCT_STAT st;
1104   char *vname = volume_label(SNUM(conn));
1105   int snum = SNUM(conn);
1106   char *fstype = lp_fstype(SNUM(conn));
1107
1108   DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1109
1110   if(vfs_stat(conn,".",&st)!=0) {
1111     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1112     return ERROR_DOS(ERRSRV,ERRinvdevice);
1113   }
1114
1115   pdata = Realloc(*ppdata, max_data_bytes + 1024);
1116   if ( pdata == NULL ) {
1117     return ERROR_DOS(ERRDOS,ERRnomem);
1118   }
1119   *ppdata       = pdata;
1120   memset((char *)pdata,'\0',max_data_bytes + 1024);
1121
1122   switch (info_level) 
1123   {
1124     case 1:
1125     {
1126       SMB_BIG_UINT dfree,dsize,bsize;
1127       data_len = 18;
1128       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);     
1129       SIVAL(pdata,l1_idFileSystem,st.st_dev);
1130       SIVAL(pdata,l1_cSectorUnit,bsize/512);
1131       SIVAL(pdata,l1_cUnit,dsize);
1132       SIVAL(pdata,l1_cUnitAvail,dfree);
1133       SSVAL(pdata,l1_cbSector,512);
1134       DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1135                  (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1136          (unsigned int)dfree, 512));
1137       break;
1138     }
1139     case 2:
1140             /* Return volume name */
1141             /* 
1142              * Add volume serial number - hash of a combination of
1143              * the called hostname and the service name.
1144              */
1145             SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1146             len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 
1147                               STR_TERMINATE);
1148             SCVAL(pdata,l2_vol_cch,len);
1149             data_len = l2_vol_szVolLabel + len;
1150             DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1151                      (unsigned)st.st_ctime, len, vname));
1152             break;
1153
1154     case SMB_QUERY_FS_ATTRIBUTE_INFO:
1155             SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1156                   (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1157             SIVAL(pdata,4,255); /* Max filename component length */
1158             len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_TERMINATE);
1159             SIVAL(pdata,8,len);
1160             data_len = 12 + len;
1161             break;
1162
1163     case SMB_QUERY_FS_LABEL_INFO:
1164             len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1165             data_len = 4 + len;
1166             SIVAL(pdata,0,len);
1167             break;
1168     case SMB_QUERY_FS_VOLUME_INFO:      
1169             /* 
1170              * Add volume serial number - hash of a combination of
1171              * the called hostname and the service name.
1172              */
1173             SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1174                   (str_checksum(local_machine)<<16));
1175
1176             len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1177             SIVAL(pdata,12,len);
1178             data_len = 18+len;
1179             DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
1180                      (int)strlen(vname),vname, lp_servicename(snum)));
1181             break;
1182     case SMB_QUERY_FS_SIZE_INFO:
1183     {
1184       SMB_BIG_UINT dfree,dsize,bsize;
1185       data_len = 24;
1186       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);     
1187       SBIG_UINT(pdata,0,dsize);
1188       SBIG_UINT(pdata,8,dfree);
1189       SIVAL(pdata,16,bsize/512);
1190       SIVAL(pdata,20,512);
1191       break;
1192     }
1193     case SMB_QUERY_FS_DEVICE_INFO:
1194       data_len = 8;
1195       SIVAL(pdata,0,0); /* dev type */
1196       SIVAL(pdata,4,0); /* characteristics */
1197       break;
1198     case SMB_MAC_QUERY_FS_INFO:
1199             /*
1200              * Thursby MAC extension... ONLY on NTFS filesystems
1201              * once we do streams then we don't need this
1202              */
1203             if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1204                     data_len = 88;
1205                     SIVAL(pdata,84,0x100); /* Don't support mac... */
1206                     break;
1207             }
1208             /* drop through */
1209   default:
1210           return ERROR_DOS(ERRDOS,ERRunknownlevel);
1211   }
1212
1213
1214   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1215
1216   DEBUG( 4, ( "%s info_level = %d\n",
1217             smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1218
1219   return -1;
1220 }
1221
1222 /****************************************************************************
1223  Reply to a TRANS2_SETFSINFO (set filesystem info).
1224 ****************************************************************************/
1225
1226 static int call_trans2setfsinfo(connection_struct *conn,
1227                                 char *inbuf, char *outbuf, int length, 
1228                                 int bufsize,
1229                                 char **pparams, char **ppdata)
1230 {
1231   /* Just say yes we did it - there is nothing that
1232      can be set here so it doesn't matter. */
1233   int outsize;
1234   DEBUG(3,("call_trans2setfsinfo\n"));
1235
1236   if (!CAN_WRITE(conn))
1237     return ERROR_DOS(ERRSRV,ERRaccess);
1238
1239   outsize = set_message(outbuf,10,0,True);
1240
1241   return outsize;
1242 }
1243
1244 /****************************************************************************
1245  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1246  file name or file id).
1247 ****************************************************************************/
1248
1249 static int call_trans2qfilepathinfo(connection_struct *conn,
1250                                     char *inbuf, char *outbuf, int length, 
1251                                     int bufsize,
1252                                     char **pparams,char **ppdata,
1253                                     int total_data)
1254 {
1255         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1256         char *params = *pparams;
1257         char *pdata = *ppdata;
1258         uint16 tran_call = SVAL(inbuf, smb_setup0);
1259         uint16 info_level;
1260         int mode=0;
1261         SMB_OFF_T size=0;
1262         SMB_OFF_T allocation_size=0;
1263         unsigned int data_size;
1264         SMB_STRUCT_STAT sbuf;
1265         pstring fname;
1266         char *base_name;
1267         char *p;
1268         SMB_OFF_T pos = 0;
1269         BOOL bad_path = False;
1270         BOOL delete_pending = False;
1271         int len;
1272         time_t c_time;
1273
1274         if (tran_call == TRANSACT2_QFILEINFO) {
1275                 files_struct *fsp = file_fsp(params,0);
1276                 info_level = SVAL(params,2);
1277
1278                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1279
1280                 if(fsp && (fsp->is_directory || fsp->stat_open)) {
1281                         /*
1282                          * This is actually a QFILEINFO on a directory
1283                          * handle (returned from an NT SMB). NT5.0 seems
1284                          * to do this call. JRA.
1285                          */
1286                         pstrcpy(fname, fsp->fsp_name);
1287                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1288                         if (!check_name(fname,conn) || 
1289                                         (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1290                                 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1291                                 if((errno == ENOENT) && bad_path) {
1292                                         unix_ERR_class = ERRDOS;
1293                                         unix_ERR_code = ERRbadpath;
1294                                 }
1295                                 return(UNIXERROR(ERRDOS,ERRbadpath));
1296                         }
1297                   
1298                         delete_pending = fsp->directory_delete_on_close;
1299                 } else {
1300                         /*
1301                          * Original code - this is an open file.
1302                          */
1303                         CHECK_FSP(fsp,conn);
1304
1305                         pstrcpy(fname, fsp->fsp_name);
1306                         if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1307                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1308                                 return(UNIXERROR(ERRDOS,ERRbadfid));
1309                         }
1310                         if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1311                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1312
1313                         delete_pending = fsp->delete_on_close;
1314                 }
1315         } else {
1316                 /* qpathinfo */
1317                 info_level = SVAL(params,0);
1318
1319                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1320
1321                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1322
1323                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1324
1325                 unix_convert(fname,conn,0,&bad_path,&sbuf);
1326                 if (!check_name(fname,conn) || 
1327                                 (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1328                         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1329                         if((errno == ENOENT) && bad_path) {
1330                                 unix_ERR_class = ERRDOS;
1331                                 unix_ERR_code = ERRbadpath;
1332                         }
1333                         return(UNIXERROR(ERRDOS,ERRbadpath));
1334                 }
1335         }
1336
1337
1338         DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1339                 fname,info_level,tran_call,total_data));
1340
1341         p = strrchr_m(fname,'/'); 
1342         if (!p)
1343                 base_name = fname;
1344         else
1345                 base_name = p+1;
1346
1347         mode = dos_mode(conn,fname,&sbuf);
1348         size = sbuf.st_size;
1349         allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
1350         
1351         if (mode & aDIR)
1352                 size = 0;
1353
1354         params = Realloc(*pparams,2);
1355         if (params == NULL)
1356           return ERROR_DOS(ERRDOS,ERRnomem);
1357         *pparams = params;
1358         memset((char *)params,'\0',2);
1359         data_size = max_data_bytes + 1024;
1360         pdata = Realloc(*ppdata, data_size); 
1361         if ( pdata == NULL )
1362                 return ERROR_DOS(ERRDOS,ERRnomem);
1363         *ppdata = pdata;
1364
1365         if (total_data > 0 && IVAL(pdata,0) == total_data) {
1366                 /* uggh, EAs for OS2 */
1367                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1368                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1369         }
1370
1371         memset((char *)pdata,'\0',data_size);
1372
1373         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1374
1375         if (lp_dos_filetime_resolution(SNUM(conn))) {
1376                 c_time &= ~1;
1377                 sbuf.st_atime &= ~1;
1378                 sbuf.st_mtime &= ~1;
1379                 sbuf.st_mtime &= ~1;
1380         }
1381
1382         switch (info_level) {
1383                 case SMB_INFO_STANDARD:
1384                 case SMB_INFO_QUERY_EA_SIZE:
1385                         data_size = (info_level==1?22:26);
1386                         put_dos_date2(pdata,l1_fdateCreation,c_time);
1387                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1388                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1389                         SIVAL(pdata,l1_cbFile,(uint32)size);
1390                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1391                         SSVAL(pdata,l1_attrFile,mode);
1392                         SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1393                         break;
1394
1395                 case SMB_INFO_QUERY_EAS_FROM_LIST:
1396                         data_size = 24;
1397                         put_dos_date2(pdata,0,c_time);
1398                         put_dos_date2(pdata,4,sbuf.st_atime);
1399                         put_dos_date2(pdata,8,sbuf.st_mtime);
1400                         SIVAL(pdata,12,(uint32)size);
1401                         SIVAL(pdata,16,(uint32)allocation_size);
1402                         SIVAL(pdata,20,mode);
1403                         break;
1404
1405                 case SMB_INFO_QUERY_ALL_EAS:
1406                         data_size = 4;
1407                         SIVAL(pdata,0,data_size);
1408                         break;
1409
1410                 case 6:
1411                         return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */      
1412
1413                 case SMB_FILE_BASIC_INFORMATION:
1414                 case SMB_QUERY_FILE_BASIC_INFO:
1415
1416                         if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1417                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1418                         else {
1419                                 data_size = 40;
1420                                 SIVAL(pdata,36,0);
1421                         }
1422                         put_long_date(pdata,c_time);
1423                         put_long_date(pdata+8,sbuf.st_atime);
1424                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1425                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1426                         SIVAL(pdata,32,mode);
1427
1428                         DEBUG(5,("SMB_QFBI - "));
1429                         {
1430                                 time_t create_time = c_time;
1431                                 DEBUG(5,("create: %s ", ctime(&create_time)));
1432                         }
1433                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1434                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1435                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1436                         DEBUG(5,("mode: %x\n", mode));
1437
1438                         break;
1439
1440                 case SMB_FILE_STANDARD_INFORMATION:
1441                 case SMB_QUERY_FILE_STANDARD_INFO:
1442                         data_size = 24;
1443                         /* Fake up allocation size. */
1444                         SOFF_T(pdata,0,allocation_size);
1445                         SOFF_T(pdata,8,size);
1446                         SIVAL(pdata,16,sbuf.st_nlink);
1447                         CVAL(pdata,20) = 0;
1448                         CVAL(pdata,21) = (mode&aDIR)?1:0;
1449                         break;
1450
1451                 case SMB_FILE_EA_INFORMATION:
1452                 case SMB_QUERY_FILE_EA_INFO:
1453                         data_size = 4;
1454                         break;
1455
1456                 /* Get the 8.3 name - used if NT SMB was negotiated. */
1457                 case SMB_QUERY_FILE_ALT_NAME_INFO:
1458                 {
1459                         pstring short_name;
1460
1461                         pstrcpy(short_name,base_name);
1462                         /* Mangle if not already 8.3 */
1463                         if(!is_8_3(short_name, True)) {
1464                                 if(!name_map_mangle(short_name,True,True,SNUM(conn)))
1465                                         *short_name = '\0';
1466                         }
1467                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER);
1468                         data_size = 4 + len;
1469                         SIVAL(pdata,0,len);
1470                         break;
1471                 }
1472
1473                 case SMB_QUERY_FILE_NAME_INFO:
1474                         /*
1475                          * The first part of this code is essential
1476                          * to get security descriptors to work on mapped
1477                          * drives. Don't ask how I discovered this unless
1478                          * you like hearing about me suffering.... :-). JRA.
1479                          */
1480                         if(strequal(".", fname)) {
1481                                 len = srvstr_push(outbuf, pdata+4, "\\", -1, STR_TERMINATE);
1482                         } else {
1483                                 len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE);
1484                         }
1485                         data_size = 4 + len;
1486                         SIVAL(pdata,0,len);
1487                         break;
1488
1489                 case SMB_FILE_END_OF_FILE_INFORMATION:
1490                 case SMB_QUERY_FILE_END_OF_FILEINFO:
1491                         data_size = 8;
1492                         SOFF_T(pdata,0,size);
1493                         break;
1494
1495                 case SMB_FILE_ALLOCATION_INFORMATION:
1496                 case SMB_QUERY_FILE_ALLOCATION_INFO:
1497                         data_size = 8;
1498                         SOFF_T(pdata,0,allocation_size);
1499                         break;
1500
1501                 case SMB_QUERY_FILE_ALL_INFO:
1502                         put_long_date(pdata,c_time);
1503                         put_long_date(pdata+8,sbuf.st_atime);
1504                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1505                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1506                         SIVAL(pdata,32,mode);
1507                         pdata += 40;
1508                         SOFF_T(pdata,0,allocation_size);
1509                         SOFF_T(pdata,8,size);
1510                         SIVAL(pdata,16,sbuf.st_nlink);
1511                         CVAL(pdata,20) = delete_pending;
1512                         CVAL(pdata,21) = (mode&aDIR)?1:0;
1513                         pdata += 24;
1514                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); 
1515                         pdata += 8; /* index number */
1516                         pdata += 4; /* EA info */
1517                         if (mode & aRONLY)
1518                                 SIVAL(pdata,0,0xA9);
1519                         else
1520                                 SIVAL(pdata,0,0xd01BF);
1521                         pdata += 4;
1522                         SOFF_T(pdata,0,pos); /* current offset */
1523                         pdata += 8;
1524                         SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1525                         pdata += 4;
1526                         pdata += 4; /* alignment */
1527                         len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE);
1528                         SIVAL(pdata,0,len);
1529                         pdata += 4 + len;
1530                         data_size = PTR_DIFF(pdata,(*ppdata));
1531                         break;
1532
1533                 case SMB_FILE_INTERNAL_INFORMATION:
1534                         /* This should be an index number - looks like dev/ino to me :-) */
1535                         SIVAL(pdata,0,sbuf.st_dev);
1536                         SIVAL(pdata,4,sbuf.st_ino);
1537                         data_size = 8;
1538                         break;
1539
1540                 case SMB_FILE_ACCESS_INFORMATION:
1541                         SIVAL(pdata,0,0x12019F); /* ??? */
1542                         data_size = 4;
1543                         break;
1544
1545                 case SMB_FILE_NAME_INFORMATION:
1546                         /* Pathname with leading '\'. */
1547                         {
1548                                 pstring new_fname;
1549                                 size_t byte_len;
1550
1551                                 pstrcpy(new_fname, "\\");
1552                                 pstrcat(new_fname, fname);
1553                                 byte_len = dos_PutUniCode(pdata+4,new_fname,max_data_bytes,False);
1554                                 SIVAL(pdata,0,byte_len);
1555                                 data_size = 4 + byte_len;
1556                                 break;
1557                         }
1558
1559                 case SMB_FILE_DISPOSITION_INFORMATION:
1560                         data_size = 1;
1561                         CVAL(pdata,0) = delete_pending;
1562                         break;
1563
1564                 case SMB_FILE_POSITION_INFORMATION:
1565                         data_size = 8;
1566                         SOFF_T(pdata,0,pos);
1567                         break;
1568
1569                 case SMB_FILE_MODE_INFORMATION:
1570                         SIVAL(pdata,0,mode);
1571                         data_size = 4;
1572                         break;
1573
1574                 case SMB_FILE_ALIGNMENT_INFORMATION:
1575                         SIVAL(pdata,0,0); /* No alignment needed. */
1576                         data_size = 4;
1577                         break;
1578
1579 #if 0
1580         /* Not yet finished... JRA */
1581         case 1018:
1582                 {
1583                         pstring new_fname;
1584                         size_t byte_len;
1585
1586                         put_long_date(pdata,c_time);
1587                         put_long_date(pdata+8,sbuf.st_atime);
1588                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1589                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1590                         SIVAL(pdata,32,mode);
1591                         SIVAL(pdata,36,0); /* ??? */
1592                         SIVAL(pdata,40,0x20); /* ??? */
1593                         SIVAL(pdata,44,0); /* ??? */
1594                         SOFF_T(pdata,48,size);
1595                         SIVAL(pdata,56,0x1); /* ??? */
1596                         SIVAL(pdata,60,0); /* ??? */
1597                         SIVAL(pdata,64,0); /* ??? */
1598                         SIVAL(pdata,68,length); /* Following string length in bytes. */
1599                         dos_PutUniCode(pdata+72,,False);
1600                         break;
1601                 }
1602 #endif
1603
1604                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1605                         /* Last component of pathname. */
1606                         {
1607                                 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1608                                 SIVAL(pdata,0,byte_len);
1609                                 data_size = 4 + byte_len;
1610                                 break;
1611                         }
1612                 
1613                 case SMB_FILE_STREAM_INFORMATION:
1614                         if (mode & aDIR) {
1615                                 data_size = 0;
1616                         } else {
1617                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1618                                 SIVAL(pdata,0,0); /* ??? */
1619                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1620                                 SOFF_T(pdata,8,size);
1621                                 SIVAL(pdata,16,allocation_size);
1622                                 SIVAL(pdata,20,0); /* ??? */
1623                                 data_size = 24 + byte_len;
1624                         }
1625                         break;
1626
1627                 case SMB_FILE_COMPRESSION_INFORMATION:
1628                         SOFF_T(pdata,0,size);
1629                         SIVAL(pdata,8,0); /* ??? */
1630                         SIVAL(pdata,12,0); /* ??? */
1631                         data_size = 16;
1632                         break;
1633
1634                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1635                         put_long_date(pdata,c_time);
1636                         put_long_date(pdata+8,sbuf.st_atime);
1637                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1638                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1639                         SIVAL(pdata,32,allocation_size);
1640                         SOFF_T(pdata,40,size);
1641                         SIVAL(pdata,48,mode);
1642                         SIVAL(pdata,52,0); /* ??? */
1643                         data_size = 56;
1644                         break;
1645
1646                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1647                         SIVAL(pdata,0,mode);
1648                         SIVAL(pdata,4,0);
1649                         data_size = 8;
1650                         break;
1651
1652 #if 0
1653                 /* NT4 server just returns "invalid query" to this - if we try to answer 
1654                                 it then NTws gets a BSOD! (tridge) */
1655                 case SMB_QUERY_FILE_STREAM_INFO:
1656                         SIVAL(pdata,0,pos);
1657                         SIVAL(pdata,4,(uint32)size);
1658                         SIVAL(pdata,12,(uint32)allocation_size);
1659                         len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE);
1660                         SIVAL(pdata,20,len);
1661                         data_size = 24 + len;
1662                         break;
1663 #endif
1664
1665                 default:
1666                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1667         }
1668
1669         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
1670
1671         return(-1);
1672 }
1673
1674 /****************************************************************************
1675  Deal with the internal needs of setting the delete on close flag. Note that
1676  as the tdb locking is recursive, it is safe to call this from within 
1677  open_file_shared. JRA.
1678 ****************************************************************************/
1679
1680 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
1681 {
1682         /*
1683          * Only allow delete on close for files/directories opened with delete intent.
1684          */
1685
1686         if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) {
1687                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
1688                                 fsp->fsp_name ));
1689                                 return NT_STATUS_ACCESS_DENIED;
1690         }
1691
1692         if(fsp->is_directory) {
1693                 fsp->directory_delete_on_close = delete_on_close;
1694                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
1695                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1696         } else if(fsp->stat_open) {
1697
1698                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, stat open %s\n",
1699                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1700
1701         } else {
1702
1703                 files_struct *iterate_fsp;
1704
1705                 /*
1706                  * Modify the share mode entry for all files open
1707                  * on this device and inode to tell other smbds we have 
1708                  * changed the delete on close flag. This will be noticed
1709                  * in the close code, the last closer will delete the file
1710                  * if flag is set.
1711                  */
1712
1713                 DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
1714                                         delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1715
1716                 if (lock_share_entry_fsp(fsp) == False)
1717                                 return NT_STATUS_ACCESS_DENIED;
1718
1719                 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
1720                         DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
1721                                         fsp->fsp_name ));
1722                         unlock_share_entry_fsp(fsp);
1723                         return NT_STATUS_ACCESS_DENIED;
1724                 }
1725
1726                 /*
1727                  * Release the lock.
1728                  */
1729
1730                 unlock_share_entry_fsp(fsp);
1731
1732                 /*
1733                  * Go through all files we have open on the same device and
1734                  * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1735                  * Other smbd's that have this file open will look in the share_mode on close.
1736                  * take care of this (rare) case in close_file(). See the comment there.
1737                  * NB. JRA. We don't really need to do this anymore - all should be taken
1738                  * care of in the share_mode changes in the tdb.
1739                  */
1740
1741                 for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
1742                                 iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
1743                                                 fsp->delete_on_close = delete_on_close;
1744
1745                 /*
1746                  * Set the delete on close flag in the fsp.
1747                  */
1748                 fsp->delete_on_close = delete_on_close;
1749
1750                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
1751                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1752
1753         }
1754
1755         return NT_STATUS_OK;
1756 }
1757
1758 /****************************************************************************
1759  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
1760 ****************************************************************************/
1761
1762 static int call_trans2setfilepathinfo(connection_struct *conn,
1763                                       char *inbuf, char *outbuf, int length, 
1764                                       int bufsize, char **pparams, 
1765                                       char **ppdata, int total_data)
1766 {
1767         char *params = *pparams;
1768         char *pdata = *ppdata;
1769         uint16 tran_call = SVAL(inbuf, smb_setup0);
1770         uint16 info_level;
1771         int mode=0;
1772         SMB_OFF_T size=0;
1773         struct utimbuf tvs;
1774         SMB_STRUCT_STAT sbuf;
1775         pstring fname;
1776         int fd = -1;
1777         BOOL bad_path = False;
1778         files_struct *fsp = NULL;
1779
1780         if (tran_call == TRANSACT2_SETFILEINFO) {
1781                 fsp = file_fsp(params,0);
1782                 info_level = SVAL(params,2);    
1783
1784                 if(fsp && (fsp->is_directory || fsp->stat_open)) {
1785                         /*
1786                          * This is actually a SETFILEINFO on a directory
1787                          * handle (returned from an NT SMB). NT5.0 seems
1788                          * to do this call. JRA.
1789                          */
1790                         pstrcpy(fname, fsp->fsp_name);
1791                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1792                         if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
1793                                 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1794                                 if((errno == ENOENT) && bad_path) {
1795                                         unix_ERR_class = ERRDOS;
1796                                         unix_ERR_code = ERRbadpath;
1797                                 }
1798                                 return(UNIXERROR(ERRDOS,ERRbadpath));
1799                         }
1800                 } else if (fsp && fsp->print_file) {
1801                         /*
1802                          * Doing a DELETE_ON_CLOSE should cancel a print job.
1803                          */
1804                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
1805                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
1806
1807                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
1808         
1809                                 SSVAL(params,0,0);
1810                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1811                                 return(-1);
1812                         }
1813             } else {
1814                         /*
1815                          * Original code - this is an open file.
1816                          */
1817                         CHECK_FSP(fsp,conn);
1818
1819                         pstrcpy(fname, fsp->fsp_name);
1820                         fd = fsp->fd;
1821
1822                         if (vfs_fstat(fsp,fd,&sbuf) != 0) {
1823                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1824                                 return(UNIXERROR(ERRDOS,ERRbadfid));
1825                         }
1826                 }
1827         } else {
1828                 /* set path info */
1829                 info_level = SVAL(params,0);    
1830                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1831                 unix_convert(fname,conn,0,&bad_path,&sbuf);
1832                 if(!check_name(fname, conn)) {
1833                         if((errno == ENOENT) && bad_path) {
1834                                 unix_ERR_class = ERRDOS;
1835                                 unix_ERR_code = ERRbadpath;
1836                         }
1837                         return(UNIXERROR(ERRDOS,ERRbadpath));
1838                 }
1839  
1840                 if(!VALID_STAT(sbuf)) {
1841                         DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1842                         if((errno == ENOENT) && bad_path) {
1843                                 unix_ERR_class = ERRDOS;
1844                                 unix_ERR_code = ERRbadpath;
1845                         }
1846                         return(UNIXERROR(ERRDOS,ERRbadpath));
1847                 }    
1848         }
1849
1850         if (!CAN_WRITE(conn))
1851                 return ERROR_DOS(ERRSRV,ERRaccess);
1852
1853         DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1854                 tran_call,fname,info_level,total_data));
1855
1856         /* Realloc the parameter and data sizes */
1857         params = Realloc(*pparams,2);
1858         if(params == NULL)
1859                 return ERROR_DOS(ERRDOS,ERRnomem);
1860         *pparams = params;
1861
1862         SSVAL(params,0,0);
1863
1864         size = sbuf.st_size;
1865         tvs.modtime = sbuf.st_mtime;
1866         tvs.actime = sbuf.st_atime;
1867         mode = dos_mode(conn,fname,&sbuf);
1868
1869         if (total_data > 4 && IVAL(pdata,0) == total_data) {
1870                 /* uggh, EAs for OS2 */
1871                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1872                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1873         }
1874
1875         switch (info_level) {
1876                 case SMB_INFO_STANDARD:
1877                 case SMB_INFO_QUERY_EA_SIZE:
1878                 {
1879                         /* access time */
1880                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1881
1882                         /* write time */
1883                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1884
1885                         mode = SVAL(pdata,l1_attrFile);
1886                         size = IVAL(pdata,l1_cbFile);
1887                         break;
1888                 }
1889
1890                 /* XXXX um, i don't think this is right.
1891                         it's also not in the cifs6.txt spec.
1892                 */
1893                 case SMB_INFO_QUERY_EAS_FROM_LIST:
1894                         tvs.actime = make_unix_date2(pdata+8);
1895                         tvs.modtime = make_unix_date2(pdata+12);
1896                         size = IVAL(pdata,16);
1897                         mode = IVAL(pdata,24);
1898                         break;
1899
1900                 /* XXXX nor this.  not in cifs6.txt, either. */
1901                 case SMB_INFO_QUERY_ALL_EAS:
1902                         tvs.actime = make_unix_date2(pdata+8);
1903                         tvs.modtime = make_unix_date2(pdata+12);
1904                         size = IVAL(pdata,16);
1905                         mode = IVAL(pdata,24);
1906                         break;
1907
1908                 case SMB_SET_FILE_BASIC_INFO:
1909                 case SMB_FILE_BASIC_INFORMATION:
1910                 {
1911                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
1912                         time_t write_time;
1913                         time_t changed_time;
1914
1915                         /* Ignore create time at offset pdata. */
1916
1917                         /* access time */
1918                         tvs.actime = interpret_long_date(pdata+8);
1919
1920                         write_time = interpret_long_date(pdata+16);
1921                         changed_time = interpret_long_date(pdata+24);
1922
1923                         tvs.modtime = MIN(write_time, changed_time);
1924
1925                         /* Prefer a defined time to an undefined one. */
1926                         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
1927                                 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
1928                                         ? changed_time : write_time);
1929
1930                         /* attributes */
1931                         mode = IVAL(pdata,32);
1932                         break;
1933                 }
1934
1935                 case  SMB_FILE_ALLOCATION_INFORMATION:
1936                 case SMB_SET_FILE_ALLOCATION_INFO:
1937                 {
1938                         int ret = -1;
1939                         SMB_OFF_T allocation_size = IVAL(pdata,0);
1940 #ifdef LARGE_SMB_OFF_T
1941                         allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1942 #else /* LARGE_SMB_OFF_T */
1943                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
1944                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1945 #endif /* LARGE_SMB_OFF_T */
1946                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
1947                                         fname, (double)allocation_size ));
1948
1949                         if(allocation_size != sbuf.st_size) {
1950                                 SMB_STRUCT_STAT new_sbuf;
1951  
1952                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
1953                                         fname, (double)allocation_size ));
1954  
1955                                 if (fd == -1) {
1956                                         files_struct *new_fsp = NULL;
1957                                         int access_mode = 0;
1958                                         int action = 0;
1959  
1960                                         if(global_oplock_break) {
1961                                                 /* Queue this file modify as we are the process of an oplock break.  */
1962  
1963                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
1964                                                 DEBUGADD(2,( "in oplock break state.\n"));
1965  
1966                                                 push_oplock_pending_smb_message(inbuf, length);
1967                                                 return -1;
1968                                         }
1969  
1970                                         new_fsp = open_file_shared(conn, fname, &sbuf,
1971                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
1972                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1973                                                                         0, 0, &access_mode, &action);
1974  
1975                                         if (new_fsp == NULL)
1976                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
1977                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
1978                                         if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
1979                                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno)));
1980                                                 ret = -1;
1981                                         }
1982                                         close_file(new_fsp,True);
1983                                 } else {
1984                                         ret = vfs_allocate_file_space(fsp, size);
1985                                         if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
1986                                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1987                                                 ret = -1;
1988                                         }
1989                                 }
1990                                 if (ret == -1)
1991                                         return ERROR_NT(NT_STATUS_DISK_FULL);
1992
1993                                 /* Allocate can trucate size... */
1994                                 size = new_sbuf.st_size;
1995                         }
1996
1997                         break;
1998                 }
1999
2000         case SMB_FILE_END_OF_FILE_INFORMATION:
2001                 case SMB_SET_FILE_END_OF_FILE_INFO:
2002                 {
2003                         size = IVAL(pdata,0);
2004 #ifdef LARGE_SMB_OFF_T
2005                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2006 #else /* LARGE_SMB_OFF_T */
2007                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2008                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2009 #endif /* LARGE_SMB_OFF_T */
2010                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2011                         break;
2012                 }
2013
2014                 case SMB_FILE_DISPOSITION_INFORMATION:
2015                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2016                 {
2017                         BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2018                         NTSTATUS status;
2019
2020                         if (tran_call != TRANSACT2_SETFILEINFO)
2021                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2022
2023                         if (fsp == NULL)
2024                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2025
2026                         status = set_delete_on_close_internal(fsp, delete_on_close);
2027  
2028                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
2029                                 return ERROR_NT(status);
2030
2031                         break;
2032                 }
2033
2034                 default:
2035                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2036         }
2037
2038         /* get some defaults (no modifications) if any info is zero or -1. */
2039         if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2040                 tvs.actime = sbuf.st_atime;
2041
2042         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2043                 tvs.modtime = sbuf.st_mtime;
2044
2045         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2046         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2047         DEBUG(6,("size: %.0f ", (double)size));
2048         DEBUG(6,("mode: %x\n"  , mode));
2049
2050         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2051                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2052                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2053                         (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2054
2055                 /*
2056                  * Only do this test if we are not explicitly
2057                  * changing the size of a file.
2058                  */
2059                 if (!size)
2060                         size = sbuf.st_size;
2061         }
2062
2063         /*
2064          * Try and set the times, size and mode of this file -
2065          * if they are different from the current values
2066          */
2067         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2068                 if(fsp != NULL) {
2069                         /*
2070                          * This was a setfileinfo on an open file.
2071                          * NT does this a lot. It's actually pointless
2072                          * setting the time here, as it will be overwritten
2073                          * on the next write, so we save the request
2074                          * away and will set it on file code. JRA.
2075                          */
2076
2077                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2078                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2079                                 fsp->pending_modtime = tvs.modtime;
2080                         }
2081
2082                 } else {
2083
2084                         DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2085
2086                         if(file_utime(conn, fname, &tvs)!=0)
2087                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2088                 }
2089         }
2090
2091         /* check the mode isn't different, before changing it */
2092         if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) {
2093
2094                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, mode ));
2095
2096                 if(file_chmod(conn, fname, mode, NULL)) {
2097                         DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2098                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2099                 }
2100         }
2101
2102         if(size != sbuf.st_size) {
2103
2104                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2105                         fname, (double)size ));
2106
2107                 if (fd == -1) {
2108                         files_struct *new_fsp = NULL;
2109                         int access_mode = 0;
2110                         int action = 0;
2111
2112                         if(global_oplock_break) {
2113                                 /* Queue this file modify as we are the process of an oplock break.  */
2114
2115                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2116                                 DEBUGADD(2,( "in oplock break state.\n"));
2117
2118                                 push_oplock_pending_smb_message(inbuf, length);
2119                                 return -1;
2120                         }
2121
2122                         new_fsp = open_file_shared(conn, fname, &sbuf,
2123                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
2124                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2125                                                 0, 0, &access_mode, &action);
2126         
2127                         if (new_fsp == NULL)
2128                                 return(UNIXERROR(ERRDOS,ERRbadpath));
2129                         vfs_set_filelen(new_fsp, size);
2130                         close_file(new_fsp,True);
2131                 } else {
2132                         vfs_set_filelen(fsp, size);
2133                 }
2134         }
2135
2136         SSVAL(params,0,0);
2137
2138         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2139   
2140         return(-1);
2141 }
2142
2143 /****************************************************************************
2144  Reply to a TRANS2_MKDIR (make directory with extended attributes).
2145 ****************************************************************************/
2146
2147 static int call_trans2mkdir(connection_struct *conn,
2148                             char *inbuf, char *outbuf, int length, int bufsize,
2149                             char **pparams, char **ppdata)
2150 {
2151   char *params = *pparams;
2152   pstring directory;
2153   int ret = -1;
2154   SMB_STRUCT_STAT sbuf;
2155   BOOL bad_path = False;
2156
2157   if (!CAN_WRITE(conn))
2158     return ERROR_DOS(ERRSRV,ERRaccess);
2159
2160   srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
2161
2162   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2163
2164   unix_convert(directory,conn,0,&bad_path,&sbuf);
2165   if (check_name(directory,conn))
2166     ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2167   
2168   if(ret < 0)
2169     {
2170       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2171       if((errno == ENOENT) && bad_path)
2172       {
2173         unix_ERR_class = ERRDOS;
2174         unix_ERR_code = ERRbadpath;
2175       }
2176       return(UNIXERROR(ERRDOS,ERRnoaccess));
2177     }
2178
2179   /* Realloc the parameter and data sizes */
2180   params = Realloc(*pparams,2);
2181   if(params == NULL) {
2182     return ERROR_DOS(ERRDOS,ERRnomem);
2183   }
2184   *pparams      = params;
2185
2186   SSVAL(params,0,0);
2187
2188   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2189   
2190   return(-1);
2191 }
2192
2193 /****************************************************************************
2194  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2195  We don't actually do this - we just send a null response.
2196 ****************************************************************************/
2197
2198 static int call_trans2findnotifyfirst(connection_struct *conn,
2199                                       char *inbuf, char *outbuf, 
2200                                       int length, int bufsize,
2201                                       char **pparams, char **ppdata)
2202 {
2203   static uint16 fnf_handle = 257;
2204   char *params = *pparams;
2205   uint16 info_level = SVAL(params,4);
2206
2207   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2208
2209   switch (info_level) 
2210     {
2211     case 1:
2212     case 2:
2213       break;
2214     default:
2215       return ERROR_DOS(ERRDOS,ERRunknownlevel);
2216     }
2217
2218   /* Realloc the parameter and data sizes */
2219   params = Realloc(*pparams,6);
2220   if(params == NULL) {
2221     return ERROR_DOS(ERRDOS,ERRnomem);
2222   }
2223   *pparams      = params;
2224
2225   SSVAL(params,0,fnf_handle);
2226   SSVAL(params,2,0); /* No changes */
2227   SSVAL(params,4,0); /* No EA errors */
2228
2229   fnf_handle++;
2230
2231   if(fnf_handle == 0)
2232     fnf_handle = 257;
2233
2234   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2235   
2236   return(-1);
2237 }
2238
2239 /****************************************************************************
2240  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
2241  changes). Currently this does nothing.
2242 ****************************************************************************/
2243
2244 static int call_trans2findnotifynext(connection_struct *conn,
2245                                      char *inbuf, char *outbuf, 
2246                                      int length, int bufsize,
2247                                      char **pparams, char **ppdata)
2248 {
2249   char *params = *pparams;
2250
2251   DEBUG(3,("call_trans2findnotifynext\n"));
2252
2253   /* Realloc the parameter and data sizes */
2254   params = Realloc(*pparams,4);
2255   if(params == NULL) {
2256     return ERROR_DOS(ERRDOS,ERRnomem);
2257   }
2258   *pparams      = params;
2259
2260   SSVAL(params,0,0); /* No changes */
2261   SSVAL(params,2,0); /* No EA errors */
2262
2263   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2264   
2265   return(-1);
2266 }
2267
2268 /****************************************************************************
2269  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2270 ****************************************************************************/
2271
2272 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2273                                      char* outbuf, int length, int bufsize,
2274                                      char** pparams, char** ppdata)
2275 {
2276   char *params = *pparams;
2277   pstring pathname;
2278   int reply_size = 0;
2279   int max_referral_level = SVAL(params,0);
2280
2281
2282   DEBUG(10,("call_trans2getdfsreferral\n"));
2283
2284   if(!lp_host_msdfs())
2285     return ERROR_DOS(ERRDOS,ERRbadfunc);
2286
2287   srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
2288
2289   if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2290     return ERROR_DOS(ERRDOS,ERRbadfile);
2291     
2292   SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2293   send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2294
2295   return(-1);
2296 }
2297
2298 #define LMCAT_SPL       0x53
2299 #define LMFUNC_GETJOBID 0x60
2300
2301 /****************************************************************************
2302  Reply to a TRANS2_IOCTL - used for OS/2 printing.
2303 ****************************************************************************/
2304
2305 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2306                             char* outbuf, int length, int bufsize,
2307                             char** pparams, char** ppdata)
2308 {
2309   char *pdata = *ppdata;
2310   files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2311
2312   if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2313       (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2314     pdata = Realloc(*ppdata, 32);
2315     if(pdata == NULL) {
2316       return ERROR_DOS(ERRDOS,ERRnomem);
2317     }
2318     *ppdata = pdata;
2319
2320         /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
2321            CAN ACCEPT THIS IN UNICODE. JRA. */
2322
2323     SSVAL(pdata,0,fsp->print_jobid);                     /* Job number */
2324         srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
2325     srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
2326     send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
2327     return(-1);
2328   } else {
2329     DEBUG(2,("Unknown TRANS2_IOCTL\n"));
2330     return ERROR_DOS(ERRSRV,ERRerror);
2331   }
2332 }
2333
2334 /****************************************************************************
2335  Reply to a SMBfindclose (stop trans2 directory search).
2336 ****************************************************************************/
2337
2338 int reply_findclose(connection_struct *conn,
2339                     char *inbuf,char *outbuf,int length,int bufsize)
2340 {
2341         int outsize = 0;
2342         int dptr_num=SVALS(inbuf,smb_vwv0);
2343         START_PROFILE(SMBfindclose);
2344
2345         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
2346
2347         dptr_close(&dptr_num);
2348
2349         outsize = set_message(outbuf,0,0,True);
2350
2351         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
2352
2353         END_PROFILE(SMBfindclose);
2354         return(outsize);
2355 }
2356
2357 /****************************************************************************
2358  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
2359 ****************************************************************************/
2360
2361 int reply_findnclose(connection_struct *conn, 
2362                      char *inbuf,char *outbuf,int length,int bufsize)
2363 {
2364         int outsize = 0;
2365         int dptr_num= -1;
2366         START_PROFILE(SMBfindnclose);
2367         
2368         dptr_num = SVAL(inbuf,smb_vwv0);
2369
2370         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2371
2372         /* We never give out valid handles for a 
2373            findnotifyfirst - so any dptr_num is ok here. 
2374            Just ignore it. */
2375
2376         outsize = set_message(outbuf,0,0,True);
2377
2378         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2379
2380         END_PROFILE(SMBfindnclose);
2381         return(outsize);
2382 }
2383
2384 /****************************************************************************
2385  Reply to a SMBtranss2 - just ignore it!
2386 ****************************************************************************/
2387
2388 int reply_transs2(connection_struct *conn,
2389                   char *inbuf,char *outbuf,int length,int bufsize)
2390 {
2391         START_PROFILE(SMBtranss2);
2392         DEBUG(4,("Ignoring transs2 of length %d\n",length));
2393         END_PROFILE(SMBtranss2);
2394         return(-1);
2395 }
2396
2397 /****************************************************************************
2398  Reply to a SMBtrans2.
2399 ****************************************************************************/
2400
2401 int reply_trans2(connection_struct *conn,
2402                  char *inbuf,char *outbuf,int length,int bufsize)
2403 {
2404         int outsize = 0;
2405         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2406         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2407 #if 0
2408         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2409         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2410         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2411         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2412         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2413         int32 timeout = IVALS(inbuf,smb_timeout);
2414 #endif
2415         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2416         unsigned int tran_call = SVAL(inbuf, smb_setup0);
2417         char *params = NULL, *data = NULL;
2418         int num_params, num_params_sofar, num_data, num_data_sofar;
2419         START_PROFILE(SMBtrans2);
2420
2421         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2422                 /* Queue this open message as we are the process of an
2423                  * oplock break.  */
2424
2425                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2426                 DEBUGADD(2,( "in oplock break state.\n"));
2427
2428                 push_oplock_pending_smb_message(inbuf, length);
2429                 END_PROFILE(SMBtrans2);
2430                 return -1;
2431         }
2432         
2433         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
2434             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
2435                 END_PROFILE(SMBtrans2);
2436                 return ERROR_DOS(ERRSRV,ERRaccess);
2437         }
2438
2439         outsize = set_message(outbuf,0,0,True);
2440
2441         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2442            is so as a sanity check */
2443         if (suwcnt != 1) {
2444                 /*
2445                  * Need to have rc=0 for ioctl to get job id for OS/2.
2446                  *  Network printing will fail if function is not successful.
2447                  *  Similar function in reply.c will be used if protocol
2448                  *  is LANMAN1.0 instead of LM1.2X002.
2449                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
2450                  *  outbuf doesn't have to be set(only job id is used).
2451                  */
2452                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
2453                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2454                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2455                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
2456                 } else {
2457                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
2458                         DEBUG(2,("Transaction is %d\n",tran_call));
2459                         END_PROFILE(SMBtrans2);
2460                         return ERROR_DOS(ERRSRV,ERRerror);
2461                 }
2462         }
2463     
2464         /* Allocate the space for the maximum needed parameters and data */
2465         if (total_params > 0)
2466                 params = (char *)malloc(total_params);
2467         if (total_data > 0)
2468                 data = (char *)malloc(total_data);
2469   
2470         if ((total_params && !params)  || (total_data && !data)) {
2471                 DEBUG(2,("Out of memory in reply_trans2\n"));
2472                 SAFE_FREE(params);
2473                 SAFE_FREE(data); 
2474                 END_PROFILE(SMBtrans2);
2475                 return ERROR_DOS(ERRDOS,ERRnomem);
2476         }
2477
2478         /* Copy the param and data bytes sent with this request into
2479            the params buffer */
2480         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2481         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2482
2483         if (num_params > total_params || num_data > total_data)
2484                 exit_server("invalid params in reply_trans2");
2485
2486         if(params)
2487                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2488         if(data)
2489                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2490
2491         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
2492                 /* We need to send an interim response then receive the rest
2493                    of the parameter/data bytes */
2494                 outsize = set_message(outbuf,0,0,True);
2495                 if (!send_smb(smbd_server_fd(),outbuf))
2496                         exit_server("reply_trans2: send_smb failed.");
2497
2498                 while (num_data_sofar < total_data || 
2499                        num_params_sofar < total_params) {
2500                         BOOL ret;
2501
2502                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2503                         
2504                         if ((ret && 
2505                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2506                                 outsize = set_message(outbuf,0,0,True);
2507                                 if(ret)
2508                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2509                                 else
2510                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2511                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2512                                 SAFE_FREE(params);
2513                                 SAFE_FREE(data);
2514                                 END_PROFILE(SMBtrans2);
2515                                 return ERROR_DOS(ERRSRV,ERRerror);
2516                         }
2517       
2518                         /* Revise total_params and total_data in case
2519                            they have changed downwards */
2520                         total_params = SVAL(inbuf, smb_tpscnt);
2521                         total_data = SVAL(inbuf, smb_tdscnt);
2522                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2523                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2524                         if (num_params_sofar > total_params || num_data_sofar > total_data)
2525                                 exit_server("data overflow in trans2");
2526                         
2527                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
2528                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2529                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2530                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2531                 }
2532         }
2533         
2534         if (Protocol >= PROTOCOL_NT1) {
2535                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
2536         }
2537
2538         /* Now we must call the relevant TRANS2 function */
2539         switch(tran_call)  {
2540         case TRANSACT2_OPEN:
2541                 START_PROFILE_NESTED(Trans2_open);
2542                 outsize = call_trans2open(conn, 
2543                                           inbuf, outbuf, bufsize, 
2544                                           &params, &data);
2545                 END_PROFILE_NESTED(Trans2_open);
2546                 break;
2547
2548         case TRANSACT2_FINDFIRST:
2549                 START_PROFILE_NESTED(Trans2_findfirst);
2550                 outsize = call_trans2findfirst(conn, inbuf, outbuf, 
2551                                                bufsize, &params, &data);
2552                 END_PROFILE_NESTED(Trans2_findfirst);
2553                 break;
2554
2555         case TRANSACT2_FINDNEXT:
2556                 START_PROFILE_NESTED(Trans2_findnext);
2557                 outsize = call_trans2findnext(conn, inbuf, outbuf, 
2558                                               length, bufsize, 
2559                                               &params, &data);
2560                 END_PROFILE_NESTED(Trans2_findnext);
2561                 break;
2562
2563         case TRANSACT2_QFSINFO:
2564                 START_PROFILE_NESTED(Trans2_qfsinfo);
2565             outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
2566                                          length, bufsize, &params, 
2567                                          &data);
2568                 END_PROFILE_NESTED(Trans2_qfsinfo);
2569             break;
2570
2571         case TRANSACT2_SETFSINFO:
2572                 START_PROFILE_NESTED(Trans2_setfsinfo);
2573                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
2574                                                length, bufsize, 
2575                                                &params, &data);
2576                 END_PROFILE_NESTED(Trans2_setfsinfo);
2577                 break;
2578
2579         case TRANSACT2_QPATHINFO:
2580         case TRANSACT2_QFILEINFO:
2581                 START_PROFILE_NESTED(Trans2_qpathinfo);
2582                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
2583                                                    length, bufsize, 
2584                                                    &params, &data, total_data);
2585                 END_PROFILE_NESTED(Trans2_qpathinfo);
2586                 break;
2587         case TRANSACT2_SETPATHINFO:
2588         case TRANSACT2_SETFILEINFO:
2589                 START_PROFILE_NESTED(Trans2_setpathinfo);
2590                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
2591                                                      length, bufsize, 
2592                                                      &params, &data, 
2593                                                      total_data);
2594                 END_PROFILE_NESTED(Trans2_setpathinfo);
2595                 break;
2596
2597         case TRANSACT2_FINDNOTIFYFIRST:
2598                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
2599                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
2600                                                      length, bufsize, 
2601                                                      &params, &data);
2602                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
2603                 break;
2604
2605         case TRANSACT2_FINDNOTIFYNEXT:
2606                 START_PROFILE_NESTED(Trans2_findnotifynext);
2607                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
2608                                                     length, bufsize, 
2609                                                     &params, &data);
2610                 END_PROFILE_NESTED(Trans2_findnotifynext);
2611                 break;
2612         case TRANSACT2_MKDIR:
2613                 START_PROFILE_NESTED(Trans2_mkdir);
2614                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
2615                                            bufsize, &params, &data);
2616                 END_PROFILE_NESTED(Trans2_mkdir);
2617                 break;
2618
2619         case TRANSACT2_GET_DFS_REFERRAL:
2620                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
2621         outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
2622                                             bufsize, &params, &data);
2623                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
2624                 break;
2625         case TRANSACT2_IOCTL:
2626                 START_PROFILE_NESTED(Trans2_ioctl);
2627                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length,
2628                                                 bufsize,&params,&data);
2629                 END_PROFILE_NESTED(Trans2_ioctl);
2630                 break;
2631         default:
2632                 /* Error in request */
2633                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2634                 SAFE_FREE(params);
2635                 SAFE_FREE(data);
2636                 END_PROFILE(SMBtrans2);
2637                 return ERROR_DOS(ERRSRV,ERRerror);
2638         }
2639         
2640         /* As we do not know how many data packets will need to be
2641            returned here the various call_trans2xxxx calls
2642            must send their own. Thus a call_trans2xxx routine only
2643            returns a value other than -1 when it wants to send
2644            an error packet. 
2645         */
2646         
2647         SAFE_FREE(params);
2648         SAFE_FREE(data);
2649         END_PROFILE(SMBtrans2);
2650         return outsize; /* If a correct response was needed the
2651                            call_trans2xxx calls have already sent
2652                            it. If outsize != -1 then it is returning */
2653 }