Makefile: Added AIX 3.2.5.
[samba.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-1998
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 #include "trans2.h"
26
27 extern int DEBUGLEVEL;
28 extern int Protocol;
29 extern connection_struct Connections[];
30 extern files_struct Files[];
31 extern BOOL case_sensitive;
32 extern int Client;
33 extern int oplock_sock;
34 extern int smb_read_error;
35 extern fstring local_machine;
36
37 /****************************************************************************
38   Send the required number of replies back.
39   We assume all fields other than the data fields are
40   set correctly for the type of call.
41   HACK ! Always assumes smb_setup field is zero.
42 ****************************************************************************/
43 static int send_trans2_replies(char *outbuf, int bufsize, char *params, 
44                          int paramsize, char *pdata, int datasize)
45 {
46   /* As we are using a protocol > LANMAN1 then the max_send
47      variable must have been set in the sessetupX call.
48      This takes precedence over the max_xmit field in the
49      global struct. These different max_xmit variables should
50      be merged as this is now too confusing */
51
52   extern int max_send;
53   int data_to_send = datasize;
54   int params_to_send = paramsize;
55   int useable_space;
56   char *pp = params;
57   char *pd = pdata;
58   int params_sent_thistime, data_sent_thistime, total_sent_thistime;
59   int alignment_offset = 3;
60   int data_alignment_offset = 0;
61
62   /* Initially set the wcnt area to be 10 - this is true for all
63      trans2 replies */
64   set_message(outbuf,10,0,True);
65
66   /* If there genuinely are no parameters or data to send just send
67      the empty packet */
68   if(params_to_send == 0 && data_to_send == 0)
69     {
70       send_smb(Client,outbuf);
71       return 0;
72     }
73
74   /* When sending params and data ensure that both are nicely aligned */
75   /* Only do this alignment when there is also data to send - else
76      can cause NT redirector problems. */
77   if (((params_to_send % 4) != 0) && (data_to_send != 0))
78           data_alignment_offset = 4 - (params_to_send % 4);
79
80   /* Space is bufsize minus Netbios over TCP header minus SMB header */
81   /* The alignment_offset is to align the param bytes on an even byte
82      boundary. NT 4.0 Beta needs this to work correctly. */
83   useable_space = bufsize - ((smb_buf(outbuf)+
84                               alignment_offset+data_alignment_offset) - 
85                              outbuf);
86
87   /* useable_space can never be more than max_send minus the
88      alignment offset. */
89   useable_space = MIN(useable_space, 
90                       max_send - (alignment_offset+data_alignment_offset));
91
92
93   while (params_to_send || data_to_send)
94     {
95       /* Calculate whether we will totally or partially fill this packet */
96       total_sent_thistime = params_to_send + data_to_send + 
97               alignment_offset + data_alignment_offset;
98       /* We can never send more than useable_space */
99       total_sent_thistime = MIN(total_sent_thistime, useable_space);
100
101       set_message(outbuf, 10, total_sent_thistime, True);
102
103       /* Set total params and data to be sent */
104       SSVAL(outbuf,smb_tprcnt,paramsize);
105       SSVAL(outbuf,smb_tdrcnt,datasize);
106
107       /* Calculate how many parameters and data we can fit into
108          this packet. Parameters get precedence */
109
110       params_sent_thistime = MIN(params_to_send,useable_space);
111       data_sent_thistime = useable_space - params_sent_thistime;
112       data_sent_thistime = MIN(data_sent_thistime,data_to_send);
113
114       SSVAL(outbuf,smb_prcnt, params_sent_thistime);
115       if(params_sent_thistime == 0)
116         {
117           SSVAL(outbuf,smb_proff,0);
118           SSVAL(outbuf,smb_prdisp,0);
119         } else {
120           /* smb_proff is the offset from the start of the SMB header to the
121              parameter bytes, however the first 4 bytes of outbuf are
122              the Netbios over TCP header. Thus use smb_base() to subtract
123              them from the calculation */
124           SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
125           /* Absolute displacement of param bytes sent in this packet */
126           SSVAL(outbuf,smb_prdisp,pp - params);
127         }
128
129       SSVAL(outbuf,smb_drcnt, data_sent_thistime);
130       if(data_sent_thistime == 0)
131         {
132           SSVAL(outbuf,smb_droff,0);
133           SSVAL(outbuf,smb_drdisp, 0);
134         } else {
135           /* The offset of the data bytes is the offset of the
136              parameter bytes plus the number of parameters being sent this time */
137           SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
138                                   smb_base(outbuf)) + 
139                 params_sent_thistime + data_alignment_offset);
140           SSVAL(outbuf,smb_drdisp, pd - pdata);
141         }
142
143       /* Copy the param bytes into the packet */
144       if(params_sent_thistime)
145         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
146       /* Copy in the data bytes */
147       if(data_sent_thistime)
148         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+data_alignment_offset,pd,data_sent_thistime);
149
150       DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
151                params_sent_thistime, data_sent_thistime, useable_space));
152       DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
153                params_to_send, data_to_send, paramsize, datasize));
154
155       /* Send the packet */
156       send_smb(Client,outbuf);
157
158       pp += params_sent_thistime;
159       pd += data_sent_thistime;
160
161       params_to_send -= params_sent_thistime;
162       data_to_send -= data_sent_thistime;
163
164       /* Sanity check */
165       if(params_to_send < 0 || data_to_send < 0)
166         {
167           DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
168                    params_to_send, data_to_send));
169           return -1;
170         }
171     }
172
173   return 0;
174 }
175
176
177 /****************************************************************************
178   reply to a TRANSACT2_OPEN
179 ****************************************************************************/
180 static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, 
181                     char **pparams, char **ppdata)
182 {
183   char *params = *pparams;
184   int16 open_mode = SVAL(params, 2);
185   int16 open_attr = SVAL(params,6);
186   BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
187 #if 0
188   BOOL return_additional_info = BITSETW(params,0);
189   int16 open_sattr = SVAL(params, 4);
190   time_t open_time = make_unix_date3(params+8);
191 #endif
192   int16 open_ofun = SVAL(params,12);
193   int32 open_size = IVAL(params,14);
194   char *pname = &params[28];
195   int16 namelen = strlen(pname)+1;
196
197   pstring fname;
198   int fnum = -1;
199   int unixmode;
200   int size=0,fmode=0,mtime=0,rmode;
201   int32 inode = 0;
202   struct stat sbuf;
203   int smb_action = 0;
204   BOOL bad_path = False;
205
206   StrnCpy(fname,pname,namelen);
207
208   DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
209            fname,cnum,open_mode, open_attr, open_ofun, open_size));
210
211   /* XXXX we need to handle passed times, sattr and flags */
212
213   unix_convert(fname,cnum,0,&bad_path);
214     
215   fnum = find_free_file();
216   if (fnum < 0)
217     return(ERROR(ERRSRV,ERRnofids));
218
219   if (!check_name(fname,cnum))
220   {
221     if((errno == ENOENT) && bad_path)
222     {
223       unix_ERR_class = ERRDOS;
224       unix_ERR_code = ERRbadpath;
225     }
226     Files[fnum].reserved = False;
227     return(UNIXERROR(ERRDOS,ERRnoaccess));
228   }
229
230   unixmode = unix_mode(cnum,open_attr | aARCH);
231       
232       
233   open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
234                    oplock_request, &rmode,&smb_action);
235       
236   if (!Files[fnum].open)
237   {
238     if((errno == ENOENT) && bad_path)
239     {
240       unix_ERR_class = ERRDOS;
241       unix_ERR_code = ERRbadpath;
242     }
243     Files[fnum].reserved = False;
244     return(UNIXERROR(ERRDOS,ERRnoaccess));
245   }
246
247   if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
248     close_file(fnum,False);
249     return(ERROR(ERRDOS,ERRnoaccess));
250   }
251     
252   size = sbuf.st_size;
253   fmode = dos_mode(cnum,fname,&sbuf);
254   mtime = sbuf.st_mtime;
255   inode = sbuf.st_ino;
256   if (fmode & aDIR) {
257     close_file(fnum,False);
258     return(ERROR(ERRDOS,ERRnoaccess));
259   }
260
261   /* Realloc the size of parameters and data we will return */
262   params = *pparams = Realloc(*pparams, 28);
263   if(params == NULL)
264     return(ERROR(ERRDOS,ERRnomem));
265
266   bzero(params,28);
267   SSVAL(params,0,fnum);
268   SSVAL(params,2,fmode);
269   put_dos_date2(params,4, mtime);
270   SIVAL(params,8, size);
271   SSVAL(params,12,rmode);
272
273   if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
274     smb_action |= EXTENDED_OPLOCK_GRANTED;
275   }
276
277   SSVAL(params,18,smb_action);
278   SIVAL(params,20,inode);
279  
280   /* Send the required number of replies */
281   send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
282
283   return -1;
284 }
285
286 /****************************************************************************
287   get a level dependent lanman2 dir entry.
288 ****************************************************************************/
289 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
290                                  int requires_resume_key,
291                                  BOOL dont_descend,char **ppdata, 
292                                  char *base_data, int space_remaining, 
293                                  BOOL *out_of_space,
294                                  int *last_name_off)
295 {
296   char *dname;
297   BOOL found = False;
298   struct stat sbuf;
299   pstring mask;
300   pstring pathreal;
301   pstring fname;
302   BOOL matched;
303   char *p, *pdata = *ppdata;
304   int reskey=0, prev_dirpos=0;
305   int mode=0;
306   uint32 size=0,len;
307   uint32 mdate=0, adate=0, cdate=0;
308   char *nameptr;
309   BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
310                     strequal(Connections[cnum].dirpath,".") ||
311                     strequal(Connections[cnum].dirpath,"/"));
312   BOOL was_8_3;
313   int nt_extmode; /* Used for NT connections instead of mode */
314   BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
315
316   *fname = 0;
317   *out_of_space = False;
318
319   if (!Connections[cnum].dirptr)
320     return(False);
321
322   p = strrchr(path_mask,'/');
323   if(p != NULL)
324     {
325       if(p[1] == '\0')
326         strcpy(mask,"*.*");
327       else
328         pstrcpy(mask, p+1);
329     }
330   else
331     pstrcpy(mask, path_mask);
332
333   while (!found)
334     {
335       /* Needed if we run out of space */
336       prev_dirpos = TellDir(Connections[cnum].dirptr);
337       dname = ReadDirName(Connections[cnum].dirptr);
338
339       reskey = TellDir(Connections[cnum].dirptr);
340
341       DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
342                Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
343       
344       if (!dname) 
345         return(False);
346
347       matched = False;
348
349       pstrcpy(fname,dname);      
350
351       if(mask_match(fname, mask, case_sensitive, True))
352         {
353           BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
354           if (dont_descend && !isdots)
355             continue;
356           
357           if (isrootdir && isdots)
358             continue;
359
360           pstrcpy(pathreal,Connections[cnum].dirpath);
361           if(needslash)
362             strcat(pathreal,"/");
363           strcat(pathreal,dname);
364           if (sys_stat(pathreal,&sbuf) != 0) 
365             {
366               DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
367               continue;
368             }
369
370           mode = dos_mode(cnum,pathreal,&sbuf);
371
372           if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
373             DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
374             continue;
375           }
376
377           size = sbuf.st_size;
378           mdate = sbuf.st_mtime;
379           adate = get_access_time(&sbuf);
380           cdate = get_create_time(&sbuf);
381           if(mode & aDIR)
382             size = 0;
383
384           DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
385           
386           found = True;
387         }
388     }
389
390   name_map_mangle(fname,False,SNUM(cnum));
391
392   p = pdata;
393   nameptr = p;
394
395   nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
396
397   switch (info_level)
398     {
399     case 1:
400       if(requires_resume_key) {
401         SIVAL(p,0,reskey);
402         p += 4;
403       }
404       put_dos_date2(p,l1_fdateCreation,cdate);
405       put_dos_date2(p,l1_fdateLastAccess,adate);
406       put_dos_date2(p,l1_fdateLastWrite,mdate);
407       SIVAL(p,l1_cbFile,size);
408       SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
409       SSVAL(p,l1_attrFile,mode);
410       SCVAL(p,l1_cchName,strlen(fname));
411       strcpy(p + l1_achName, fname);
412       nameptr = p + l1_achName;
413       p += l1_achName + strlen(fname) + 1;
414       break;
415
416     case 2:
417       /* info_level 2 */
418       if(requires_resume_key) {
419         SIVAL(p,0,reskey);
420         p += 4;
421       }
422       put_dos_date2(p,l2_fdateCreation,cdate);
423       put_dos_date2(p,l2_fdateLastAccess,adate);
424       put_dos_date2(p,l2_fdateLastWrite,mdate);
425       SIVAL(p,l2_cbFile,size);
426       SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
427       SSVAL(p,l2_attrFile,mode);
428       SIVAL(p,l2_cbList,0); /* No extended attributes */
429       SCVAL(p,l2_cchName,strlen(fname));
430       strcpy(p + l2_achName, fname);
431       nameptr = p + l2_achName;
432       p += l2_achName + strlen(fname) + 1;
433       break;
434
435     case 3:
436       SIVAL(p,0,reskey);
437       put_dos_date2(p,4,cdate);
438       put_dos_date2(p,8,adate);
439       put_dos_date2(p,12,mdate);
440       SIVAL(p,16,size);
441       SIVAL(p,20,ROUNDUP(size,1024));
442       SSVAL(p,24,mode);
443       SIVAL(p,26,4);
444       CVAL(p,30) = strlen(fname);
445       strcpy(p+31, fname);
446       nameptr = p+31;
447       p += 31 + strlen(fname) + 1;
448       break;
449
450     case 4:
451       if(requires_resume_key) {
452         SIVAL(p,0,reskey);
453         p += 4;
454       }
455       SIVAL(p,0,33+strlen(fname)+1);
456       put_dos_date2(p,4,cdate);
457       put_dos_date2(p,8,adate);
458       put_dos_date2(p,12,mdate);
459       SIVAL(p,16,size);
460       SIVAL(p,20,ROUNDUP(size,1024));
461       SSVAL(p,24,mode);
462       CVAL(p,32) = strlen(fname);
463       strcpy(p + 33, fname);
464       nameptr = p+33;
465       p += 33 + strlen(fname) + 1;
466       break;
467
468     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
469       was_8_3 = is_8_3(fname, True);
470       len = 94+strlen(fname);
471       len = (len + 3) & ~3;
472       SIVAL(p,0,len); p += 4;
473       SIVAL(p,0,reskey); p += 4;
474       put_long_date(p,cdate); p += 8;
475       put_long_date(p,adate); p += 8;
476       put_long_date(p,mdate); p += 8;
477       put_long_date(p,mdate); p += 8;
478       SIVAL(p,0,size); p += 8;
479       SIVAL(p,0,size); p += 8;
480       SIVAL(p,0,nt_extmode); p += 4;
481       SIVAL(p,0,strlen(fname)); p += 4;
482       SIVAL(p,0,0); p += 4;
483       if (!was_8_3) {
484         strcpy(p+2,fname);
485         if (!name_map_mangle(p+2,True,SNUM(cnum)))
486           (p+2)[12] = 0;
487       } else
488         *(p+2) = 0;
489       strupper(p+2);
490       SSVAL(p,0,strlen(p+2));
491       p += 2 + 24;
492       /* nameptr = p;  */
493       strcpy(p,fname); p += strlen(p);
494       p = pdata + len;
495       break;
496
497     case SMB_FIND_FILE_DIRECTORY_INFO:
498       len = 64+strlen(fname);
499       len = (len + 3) & ~3;
500       SIVAL(p,0,len); 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       SIVAL(p,0,size); p += 8;
507       SIVAL(p,0,size); p += 8;
508       SIVAL(p,0,nt_extmode); p += 4;
509       SIVAL(p,0,strlen(fname)); p += 4;
510       strcpy(p,fname);
511       p = pdata + len;
512       break;
513       
514       
515     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
516       len = 68+strlen(fname);
517       len = (len + 3) & ~3;
518       SIVAL(p,0,len); p += 4;
519       SIVAL(p,0,reskey); p += 4;
520       put_long_date(p,cdate); p += 8;
521       put_long_date(p,adate); p += 8;
522       put_long_date(p,mdate); p += 8;
523       put_long_date(p,mdate); p += 8;
524       SIVAL(p,0,size); p += 8;
525       SIVAL(p,0,size); p += 8;
526       SIVAL(p,0,nt_extmode); p += 4;
527       SIVAL(p,0,strlen(fname)); p += 4;
528       SIVAL(p,0,0); p += 4;
529       strcpy(p,fname);
530       p = pdata + len;
531       break;
532
533     case SMB_FIND_FILE_NAMES_INFO:
534       len = 12+strlen(fname);
535       len = (len + 3) & ~3;
536       SIVAL(p,0,len); p += 4;
537       SIVAL(p,0,reskey); p += 4;
538       SIVAL(p,0,strlen(fname)); p += 4;
539       strcpy(p,fname);
540       p = pdata + len;
541       break;
542
543     default:      
544       return(False);
545     }
546
547
548   if (PTR_DIFF(p,pdata) > space_remaining) {
549     /* Move the dirptr back to prev_dirpos */
550     SeekDir(Connections[cnum].dirptr, prev_dirpos);
551     *out_of_space = True;
552     DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
553     return False; /* Not finished - just out of space */
554   }
555
556   /* Setup the last_filename pointer, as an offset from base_data */
557   *last_name_off = PTR_DIFF(nameptr,base_data);
558   /* Advance the data pointer to the next slot */
559   *ppdata = p;
560   return(found);
561 }
562   
563 /****************************************************************************
564   reply to a TRANS2_FINDFIRST
565 ****************************************************************************/
566 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum, 
567                          char **pparams, char **ppdata)
568 {
569   /* We must be careful here that we don't return more than the
570      allowed number of data bytes. If this means returning fewer than
571      maxentries then so be it. We assume that the redirector has
572      enough room for the fixed number of parameter bytes it has
573      requested. */
574   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
575   char *params = *pparams;
576   char *pdata = *ppdata;
577   int dirtype = SVAL(params,0);
578   int maxentries = SVAL(params,2);
579   BOOL close_after_first = BITSETW(params+4,0);
580   BOOL close_if_end = BITSETW(params+4,1);
581   BOOL requires_resume_key = BITSETW(params+4,2);
582   int info_level = SVAL(params,6);
583   pstring directory;
584   pstring mask;
585   char *p, *wcard;
586   int last_name_off=0;
587   int dptr_num = -1;
588   int numentries = 0;
589   int i;
590   BOOL finished = False;
591   BOOL dont_descend = False;
592   BOOL out_of_space = False;
593   int space_remaining;
594   BOOL bad_path = False;
595
596   *directory = *mask = 0;
597
598   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",
599            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
600            info_level, max_data_bytes));
601   
602   switch (info_level) 
603     {
604     case 1:
605     case 2:
606     case 3:
607     case 4:
608     case SMB_FIND_FILE_DIRECTORY_INFO:
609     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
610     case SMB_FIND_FILE_NAMES_INFO:
611     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
612       break;
613     default:
614       return(ERROR(ERRDOS,ERRunknownlevel));
615     }
616
617   pstrcpy(directory, params + 12); /* Complete directory path with 
618                                      wildcard mask appended */
619
620   DEBUG(5,("path=%s\n",directory));
621
622   unix_convert(directory,cnum,0,&bad_path);
623   if(!check_name(directory,cnum)) {
624     if((errno == ENOENT) && bad_path)
625     {
626       unix_ERR_class = ERRDOS;
627       unix_ERR_code = ERRbadpath;
628     }
629
630 #if 0
631     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
632     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
633        (get_remote_arch() == RA_WINNT))
634     {
635       unix_ERR_class = ERRDOS;
636       unix_ERR_code = ERRbaddirectory;
637     }
638 #endif 
639
640     return(ERROR(ERRDOS,ERRbadpath));
641   }
642
643   p = strrchr(directory,'/');
644   if(p == NULL) {
645     strcpy(mask,directory);
646     strcpy(directory,"./");
647   } else {
648     strcpy(mask,p+1);
649     *p = 0;
650   }
651
652   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
653
654   pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
655   if(!*ppdata)
656     return(ERROR(ERRDOS,ERRnomem));
657   bzero(pdata,max_data_bytes);
658
659   /* Realloc the params space */
660   params = *pparams = Realloc(*pparams, 10);
661   if(params == NULL)
662     return(ERROR(ERRDOS,ERRnomem));
663
664   dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
665   if (dptr_num < 0)
666     return(ERROR(ERRDOS,ERRbadfile));
667
668   /* convert the formatted masks */
669   {
670     p = mask;
671     while (*p) {
672       if (*p == '<') *p = '*';
673       if (*p == '>') *p = '?';
674       if (*p == '"') *p = '.';
675       p++;
676     }
677   }
678   
679   /* a special case for 16 bit apps */
680   if (strequal(mask,"????????.???")) strcpy(mask,"*");
681
682   /* handle broken clients that send us old 8.3 format */
683   string_sub(mask,"????????","*");
684   string_sub(mask,".???",".*");
685
686   /* Save the wildcard match and attribs we are using on this directory - 
687      needed as lanman2 assumes these are being saved between calls */
688
689   if(!(wcard = strdup(mask))) {
690     dptr_close(dptr_num);
691     return(ERROR(ERRDOS,ERRnomem));
692   }
693
694   dptr_set_wcard(dptr_num, wcard);
695   dptr_set_attr(dptr_num, dirtype);
696
697   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
698
699   /* We don't need to check for VOL here as this is returned by 
700      a different TRANS2 call. */
701   
702   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
703            Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
704   if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
705     dont_descend = True;
706     
707   p = pdata;
708   space_remaining = max_data_bytes;
709   out_of_space = False;
710
711   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
712     {
713
714       /* this is a heuristic to avoid seeking the dirptr except when 
715          absolutely necessary. It allows for a filename of about 40 chars */
716       if (space_remaining < DIRLEN_GUESS && numentries > 0)
717         {
718           out_of_space = True;
719           finished = False;
720         }
721       else
722         {
723           finished = 
724             !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
725                                    requires_resume_key,dont_descend,
726                                    &p,pdata,space_remaining, &out_of_space,
727                                    &last_name_off);
728         }
729
730       if (finished && out_of_space)
731         finished = False;
732
733       if (!finished && !out_of_space)
734         numentries++;
735       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
736     }
737   
738   /* Check if we can close the dirptr */
739   if(close_after_first || (finished && close_if_end))
740     {
741       dptr_close(dptr_num);
742       DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
743       dptr_num = -1;
744     }
745
746   /* 
747    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
748    * from observation of NT.
749    */
750
751   if(numentries == 0)
752     return(ERROR(ERRDOS,ERRbadfile));
753
754   /* At this point pdata points to numentries directory entries. */
755
756   /* Set up the return parameter block */
757   SSVAL(params,0,dptr_num);
758   SSVAL(params,2,numentries);
759   SSVAL(params,4,finished);
760   SSVAL(params,6,0); /* Never an EA error */
761   SSVAL(params,8,last_name_off);
762
763   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
764
765   if ((! *directory) && dptr_path(dptr_num))
766     sprintf(directory,"(%s)",dptr_path(dptr_num));
767
768   DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
769         timestring(),
770         smb_fn_name(CVAL(inbuf,smb_com)), 
771         mask,directory,cnum,dirtype,numentries));
772
773   return(-1);
774 }
775
776
777 /****************************************************************************
778   reply to a TRANS2_FINDNEXT
779 ****************************************************************************/
780 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
781                         int cnum, char **pparams, char **ppdata)
782 {
783   /* We must be careful here that we don't return more than the
784      allowed number of data bytes. If this means returning fewer than
785      maxentries then so be it. We assume that the redirector has
786      enough room for the fixed number of parameter bytes it has
787      requested. */
788   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
789   char *params = *pparams;
790   char *pdata = *ppdata;
791   int16 dptr_num = SVAL(params,0);
792   int maxentries = SVAL(params,2);
793   uint16 info_level = SVAL(params,4);
794   uint32 resume_key = IVAL(params,6);
795   BOOL close_after_request = BITSETW(params+10,0);
796   BOOL close_if_end = BITSETW(params+10,1);
797   BOOL requires_resume_key = BITSETW(params+10,2);
798   BOOL continue_bit = BITSETW(params+10,3);
799   pstring mask;
800   pstring directory;
801   char *p;
802   uint16 dirtype;
803   int numentries = 0;
804   int i, last_name_off=0;
805   BOOL finished = False;
806   BOOL dont_descend = False;
807   BOOL out_of_space = False;
808   int space_remaining;
809
810   *mask = *directory = 0;
811
812   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, close_after_request=%d, close_if_end = %d requires_resume_key = %d resume_key = %d continue=%d level = %d\n",
813            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
814            requires_resume_key, resume_key, continue_bit, info_level));
815
816   switch (info_level) 
817     {
818     case 1:
819     case 2:
820     case 3:
821     case 4:
822     case SMB_FIND_FILE_DIRECTORY_INFO:
823     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
824     case SMB_FIND_FILE_NAMES_INFO:
825     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
826       break;
827     default:
828       return(ERROR(ERRDOS,ERRunknownlevel));
829     }
830
831   pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
832   if(!*ppdata)
833     return(ERROR(ERRDOS,ERRnomem));
834   bzero(pdata,max_data_bytes);
835
836   /* Realloc the params space */
837   params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
838   if(!params)
839     return(ERROR(ERRDOS,ERRnomem));
840
841   /* Check that the dptr is valid */
842   if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
843     return(ERROR(ERRDOS,ERRnofiles));
844
845   string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
846
847   /* Get the wildcard mask from the dptr */
848   if((p = dptr_wcard(dptr_num))== NULL) {
849     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
850     return (ERROR(ERRDOS,ERRnofiles));
851   }
852   strcpy(mask, p);
853   strcpy(directory,Connections[cnum].dirpath);
854
855   /* Get the attr mask from the dptr */
856   dirtype = dptr_attr(dptr_num);
857
858   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
859            dptr_num, mask, dirtype, 
860            Connections[cnum].dirptr,
861            TellDir(Connections[cnum].dirptr)));
862
863   /* We don't need to check for VOL here as this is returned by 
864      a different TRANS2 call. */
865
866   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
867   if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
868     dont_descend = True;
869     
870   p = pdata;
871   space_remaining = max_data_bytes;
872   out_of_space = False;
873
874   /* If we have a resume key - seek to the correct position. */
875   if(requires_resume_key && !continue_bit)
876     SeekDir(Connections[cnum].dirptr, resume_key);
877
878   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
879     {
880       /* this is a heuristic to avoid seeking the dirptr except when 
881          absolutely necessary. It allows for a filename of about 40 chars */
882       if (space_remaining < DIRLEN_GUESS && numentries > 0)
883         {
884           out_of_space = True;
885           finished = False;
886         }
887       else
888         {
889           finished = 
890             !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
891                                    requires_resume_key,dont_descend,
892                                    &p,pdata,space_remaining, &out_of_space,
893                                    &last_name_off);
894         }
895
896       if (finished && out_of_space)
897         finished = False;
898
899       if (!finished && !out_of_space)
900         numentries++;
901       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
902     }
903   
904   /* Check if we can close the dirptr */
905   if(close_after_request || (finished && close_if_end))
906     {
907       dptr_close(dptr_num); /* This frees up the saved mask */
908       DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
909       dptr_num = -1;
910     }
911
912
913   /* Set up the return parameter block */
914   SSVAL(params,0,numentries);
915   SSVAL(params,2,finished);
916   SSVAL(params,4,0); /* Never an EA error */
917   SSVAL(params,6,last_name_off);
918
919   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
920
921   if ((! *directory) && dptr_path(dptr_num))
922     sprintf(directory,"(%s)",dptr_path(dptr_num));
923
924   DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
925            timestring(),
926            smb_fn_name(CVAL(inbuf,smb_com)), 
927            mask,directory,cnum,dirtype,numentries));
928
929   return(-1);
930 }
931
932 /****************************************************************************
933   reply to a TRANS2_QFSINFO (query filesystem info)
934 ****************************************************************************/
935 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
936                         int cnum, char **pparams, char **ppdata)
937 {
938   char *pdata = *ppdata;
939   char *params = *pparams;
940   uint16 info_level = SVAL(params,0);
941   int data_len;
942   struct stat st;
943   char *vname = volume_label(SNUM(cnum));
944   int snum = SNUM(cnum);
945  
946   DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
947
948   if(sys_stat(".",&st)!=0) {
949     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
950     return (ERROR(ERRSRV,ERRinvdevice));
951   }
952
953   pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
954
955   switch (info_level) 
956     {
957     case 1:
958       {
959         int dfree,dsize,bsize;
960         data_len = 18;
961         sys_disk_free(".",&bsize,&dfree,&dsize);        
962         SIVAL(pdata,l1_idFileSystem,st.st_dev);
963         SIVAL(pdata,l1_cSectorUnit,bsize/512);
964         SIVAL(pdata,l1_cUnit,dsize);
965         SIVAL(pdata,l1_cUnitAvail,dfree);
966         SSVAL(pdata,l1_cbSector,512);
967         DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
968                  bsize, st.st_dev, bsize/512, dsize, dfree, 512));
969         break;
970     }
971     case 2:
972     { 
973       /* Return volume name */
974       int volname_len = MIN(strlen(vname),11);
975       data_len = l2_vol_szVolLabel + volname_len + 1;
976       /* 
977        * Add volume serial number - hash of a combination of
978        * the called hostname and the service name.
979        */
980       SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ str_checksum(local_machine) );
981       SCVAL(pdata,l2_vol_cch,volname_len);
982       StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
983       DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
984                pdata+l2_vol_szVolLabel));
985       break;
986     }
987     case SMB_QUERY_FS_ATTRIBUTE_INFO:
988       data_len = 12 + 2*strlen(FSTYPE_STRING);
989       SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
990       SIVAL(pdata,4,128); /* Max filename component length */
991       SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
992       PutUniCode(pdata+12,FSTYPE_STRING);
993       break;
994     case SMB_QUERY_FS_LABEL_INFO:
995       data_len = 4 + strlen(vname);
996       SIVAL(pdata,0,strlen(vname));
997       strcpy(pdata+4,vname);      
998       break;
999     case SMB_QUERY_FS_VOLUME_INFO:      
1000       data_len = 18 + 2*strlen(vname);
1001       /* 
1002        * Add volume serial number - hash of a combination of
1003        * the called hostname and the service name.
1004        */
1005       SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ str_checksum(local_machine) );
1006       SIVAL(pdata,12,2*strlen(vname));
1007       PutUniCode(pdata+18,vname);      
1008       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
1009                vname));
1010       break;
1011     case SMB_QUERY_FS_SIZE_INFO:
1012       {
1013         int dfree,dsize,bsize;
1014         data_len = 24;
1015         sys_disk_free(".",&bsize,&dfree,&dsize);        
1016         SIVAL(pdata,0,dsize);
1017         SIVAL(pdata,8,dfree);
1018         SIVAL(pdata,16,bsize/512);
1019         SIVAL(pdata,20,512);
1020       }
1021       break;
1022     case SMB_QUERY_FS_DEVICE_INFO:
1023       data_len = 8;
1024       SIVAL(pdata,0,0); /* dev type */
1025       SIVAL(pdata,4,0); /* characteristics */
1026       break;
1027     default:
1028       return(ERROR(ERRDOS,ERRunknownlevel));
1029     }
1030
1031
1032   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1033
1034   DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1035
1036   return -1;
1037 }
1038
1039 /****************************************************************************
1040   reply to a TRANS2_SETFSINFO (set filesystem info)
1041 ****************************************************************************/
1042 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1043                         int cnum, char **pparams, char **ppdata)
1044 {
1045   /* Just say yes we did it - there is nothing that
1046      can be set here so it doesn't matter. */
1047   int outsize;
1048   DEBUG(3,("call_trans2setfsinfo\n"));
1049
1050   if (!CAN_WRITE(cnum))
1051     return(ERROR(ERRSRV,ERRaccess));
1052
1053   outsize = set_message(outbuf,10,0,True);
1054
1055   return outsize;
1056 }
1057
1058 /****************************************************************************
1059   reply to a TRANS2_QFILEINFO (query file info by fileid)
1060 ****************************************************************************/
1061 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, 
1062                                     int bufsize,int cnum,
1063                                     char **pparams,char **ppdata,
1064                                     int total_data)
1065 {
1066   char *params = *pparams;
1067   char *pdata = *ppdata;
1068   uint16 tran_call = SVAL(inbuf, smb_setup0);
1069   uint16 info_level;
1070   int mode=0;
1071   int size=0;
1072   unsigned int data_size;
1073   struct stat sbuf;
1074   pstring fname1;
1075   char *fname;
1076   char *p;
1077   int l,pos;
1078   BOOL bad_path = False;
1079
1080   if (tran_call == TRANSACT2_QFILEINFO) {
1081     int16 fnum = SVALS(params,0);
1082     info_level = SVAL(params,2);
1083
1084     CHECK_FNUM(fnum,cnum);
1085     CHECK_ERROR(fnum);
1086
1087     fname = Files[fnum].name;
1088     if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1089       DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1090       return(UNIXERROR(ERRDOS,ERRbadfid));
1091     }
1092     pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1093   } else {
1094     /* qpathinfo */
1095     info_level = SVAL(params,0);
1096     fname = &fname1[0];
1097     pstrcpy(fname,&params[6]);
1098     unix_convert(fname,cnum,0,&bad_path);
1099     if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1100       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1101       if((errno == ENOENT) && bad_path)
1102       {
1103         unix_ERR_class = ERRDOS;
1104         unix_ERR_code = ERRbadpath;
1105       }
1106       return(UNIXERROR(ERRDOS,ERRbadpath));
1107     }
1108     pos = 0;
1109   }
1110
1111
1112   DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1113            fname,info_level,tran_call,total_data));
1114
1115   p = strrchr(fname,'/'); 
1116   if (!p) 
1117     p = fname;
1118   else
1119     p++;
1120   l = strlen(p);  
1121   mode = dos_mode(cnum,fname,&sbuf);
1122   size = sbuf.st_size;
1123   if (mode & aDIR) size = 0;
1124   
1125   params = *pparams = Realloc(*pparams,2); bzero(params,2);
1126   data_size = 1024;
1127   pdata = *ppdata = Realloc(*ppdata, data_size); 
1128
1129   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1130     /* uggh, EAs for OS2 */
1131     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1132     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1133   }
1134
1135   bzero(pdata,data_size);
1136
1137   switch (info_level) 
1138     {
1139     case SMB_INFO_STANDARD:
1140     case SMB_INFO_QUERY_EA_SIZE:
1141       data_size = (info_level==1?22:26);
1142       if( lp_win95_bug_compatibility())
1143       {
1144         put_dos_date(pdata,l1_fdateCreation,get_create_time(&sbuf));
1145         put_dos_date(pdata,l1_fdateLastAccess,get_access_time(&sbuf));
1146         put_dos_date(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1147       }
1148       else
1149       {
1150         put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf));
1151         put_dos_date2(pdata,l1_fdateLastAccess,get_access_time(&sbuf));
1152         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1153       }
1154       SIVAL(pdata,l1_cbFile,size);
1155       SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1156       SSVAL(pdata,l1_attrFile,mode);
1157       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1158       break;
1159
1160     case SMB_INFO_QUERY_EAS_FROM_LIST:
1161       data_size = 24;
1162       put_dos_date2(pdata,0,get_create_time(&sbuf));
1163       put_dos_date2(pdata,4,get_access_time(&sbuf));
1164       put_dos_date2(pdata,8,sbuf.st_mtime);
1165       SIVAL(pdata,12,size);
1166       SIVAL(pdata,16,ROUNDUP(size,1024));
1167       SIVAL(pdata,20,mode);
1168       break;
1169
1170     case SMB_INFO_QUERY_ALL_EAS:
1171       data_size = 4;
1172       SIVAL(pdata,0,data_size);
1173       break;
1174
1175     case 6:
1176       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
1177
1178     case SMB_QUERY_FILE_BASIC_INFO:
1179       data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1180       put_long_date(pdata,get_create_time(&sbuf));
1181       put_long_date(pdata+8,get_access_time(&sbuf));
1182       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1183       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1184       SIVAL(pdata,32,mode);
1185
1186       DEBUG(5,("SMB_QFBI - "));
1187       {
1188         time_t create_time = get_create_time(&sbuf);
1189         DEBUG(5,("create: %s ", ctime(&create_time)));
1190         create_time = get_access_time(&sbuf);
1191         DEBUG(5,("access: %s ", ctime(&create_time)));
1192       }
1193       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1194       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1195       DEBUG(5,("mode: %x\n", mode));
1196
1197       break;
1198
1199     case SMB_QUERY_FILE_STANDARD_INFO:
1200       data_size = 22;
1201       SIVAL(pdata,0,size);
1202       SIVAL(pdata,8,size);
1203       SIVAL(pdata,16,sbuf.st_nlink);
1204       CVAL(pdata,20) = 0;
1205       CVAL(pdata,21) = (mode&aDIR)?1:0;
1206       break;
1207
1208     case SMB_QUERY_FILE_EA_INFO:
1209       data_size = 4;
1210       break;
1211
1212     /* Get the 8.3 name - used if NT SMB was negotiated. */
1213     case SMB_QUERY_FILE_ALT_NAME_INFO:
1214       {
1215         pstring short_name;
1216         pstrcpy(short_name,fname);
1217         /* Mangle if not already 8.3 */
1218         if(!is_8_3(short_name, True))
1219         {
1220           if(!name_map_mangle(short_name,True,SNUM(cnum)))
1221             *short_name = '\0';
1222         }
1223         strncpy(pdata + 4,short_name,12);
1224         (pdata + 4)[12] = 0;
1225         strupper(pdata + 4);
1226         l = strlen(pdata + 4);
1227         data_size = 4 + l;
1228         SIVAL(pdata,0,l);
1229       }
1230       break;
1231
1232     case SMB_QUERY_FILE_NAME_INFO:
1233       data_size = 4 + l;
1234       SIVAL(pdata,0,l);
1235       pstrcpy(pdata+4,fname);
1236       break;
1237
1238     case SMB_QUERY_FILE_ALLOCATION_INFO:
1239     case SMB_QUERY_FILE_END_OF_FILEINFO:
1240       data_size = 8;
1241       SIVAL(pdata,0,size);
1242       break;
1243
1244     case SMB_QUERY_FILE_ALL_INFO:
1245       put_long_date(pdata,get_create_time(&sbuf));
1246       put_long_date(pdata+8,get_access_time(&sbuf));
1247       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1248       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1249       SIVAL(pdata,32,mode);
1250       pdata += 40;
1251       SIVAL(pdata,0,size);
1252       SIVAL(pdata,8,size);
1253       SIVAL(pdata,16,sbuf.st_nlink);
1254       CVAL(pdata,20) = 0;
1255       CVAL(pdata,21) = (mode&aDIR)?1:0;
1256       pdata += 24;
1257       pdata += 8; /* index number */
1258       pdata += 4; /* EA info */
1259       if (mode & aRONLY)
1260         SIVAL(pdata,0,0xA9);
1261       else
1262         SIVAL(pdata,0,0xd01BF);
1263       pdata += 4;
1264       SIVAL(pdata,0,pos); /* current offset */
1265       pdata += 8;
1266       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1267       pdata += 4;
1268       pdata += 4; /* alignment */
1269       SIVAL(pdata,0,l);
1270       pstrcpy(pdata+4,fname);
1271       pdata += 4 + l;
1272       data_size = PTR_DIFF(pdata,(*ppdata));
1273       break;
1274
1275     case SMB_QUERY_FILE_STREAM_INFO:
1276       data_size = 24 + l;
1277       SIVAL(pdata,0,pos);
1278       SIVAL(pdata,4,size);
1279       SIVAL(pdata,12,size);
1280       SIVAL(pdata,20,l);        
1281       pstrcpy(pdata+24,fname);
1282       break;
1283     default:
1284       return(ERROR(ERRDOS,ERRunknownlevel));
1285     }
1286
1287   send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1288
1289   return(-1);
1290 }
1291
1292 /****************************************************************************
1293   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1294 ****************************************************************************/
1295 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, 
1296                                       int bufsize, int cnum, char **pparams, 
1297                                       char **ppdata, int total_data)
1298 {
1299   char *params = *pparams;
1300   char *pdata = *ppdata;
1301   uint16 tran_call = SVAL(inbuf, smb_setup0);
1302   uint16 info_level;
1303   int mode=0;
1304   int size=0;
1305   struct utimbuf tvs;
1306   struct stat st;
1307   pstring fname1;
1308   char *fname;
1309   int fd = -1;
1310   BOOL bad_path = False;
1311
1312   if (!CAN_WRITE(cnum))
1313     return(ERROR(ERRSRV,ERRaccess));
1314
1315   if (tran_call == TRANSACT2_SETFILEINFO) {
1316     int16 fnum = SVALS(params,0);
1317     info_level = SVAL(params,2);    
1318
1319     CHECK_FNUM(fnum,cnum);
1320     CHECK_ERROR(fnum);
1321
1322     fname = Files[fnum].name;
1323     fd = Files[fnum].fd_ptr->fd;
1324
1325     if(fstat(fd,&st)!=0) {
1326       DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1327       return(ERROR(ERRDOS,ERRbadpath));
1328     }
1329   } else {
1330     /* set path info */
1331     info_level = SVAL(params,0);    
1332     fname = fname1;
1333     pstrcpy(fname,&params[6]);
1334     unix_convert(fname,cnum,0,&bad_path);
1335     if(!check_name(fname, cnum))
1336     {
1337       if((errno == ENOENT) && bad_path)
1338       {
1339         unix_ERR_class = ERRDOS;
1340         unix_ERR_code = ERRbadpath;
1341       }
1342       return(UNIXERROR(ERRDOS,ERRbadpath));
1343     }
1344  
1345     if(sys_stat(fname,&st)!=0) {
1346       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1347       if((errno == ENOENT) && bad_path)
1348       {
1349         unix_ERR_class = ERRDOS;
1350         unix_ERR_code = ERRbadpath;
1351       }
1352       return(UNIXERROR(ERRDOS,ERRbadpath));
1353     }    
1354   }
1355
1356   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1357            tran_call,fname,info_level,total_data));
1358
1359   /* Realloc the parameter and data sizes */
1360   params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1361   if(params == NULL)
1362     return(ERROR(ERRDOS,ERRnomem));
1363
1364   size = st.st_size;
1365   tvs.modtime = st.st_mtime;
1366   tvs.actime = st.st_atime;
1367   mode = dos_mode(cnum,fname,&st);
1368
1369   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1370     /* uggh, EAs for OS2 */
1371     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1372     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1373   }
1374
1375   switch (info_level)
1376   {
1377     case SMB_INFO_STANDARD:
1378     case SMB_INFO_QUERY_EA_SIZE:
1379     {
1380       /* access time */
1381       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1382
1383       /* write time */
1384       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1385
1386       mode = SVAL(pdata,l1_attrFile);
1387       size = IVAL(pdata,l1_cbFile);
1388       break;
1389     }
1390
1391     /* XXXX um, i don't think this is right.
1392        it's also not in the cifs6.txt spec.
1393      */
1394     case SMB_INFO_QUERY_EAS_FROM_LIST:
1395       tvs.actime = make_unix_date2(pdata+8);
1396       tvs.modtime = make_unix_date2(pdata+12);
1397       size = IVAL(pdata,16);
1398       mode = IVAL(pdata,24);
1399       break;
1400
1401     /* XXXX nor this.  not in cifs6.txt, either. */
1402     case SMB_INFO_QUERY_ALL_EAS:
1403       tvs.actime = make_unix_date2(pdata+8);
1404       tvs.modtime = make_unix_date2(pdata+12);
1405       size = IVAL(pdata,16);
1406       mode = IVAL(pdata,24);
1407       break;
1408
1409     case SMB_SET_FILE_BASIC_INFO:
1410     {
1411       /* Ignore create time at offset pdata. */
1412
1413       /* access time */
1414       tvs.actime = interpret_long_date(pdata+8);
1415
1416       /* write time + changed time, combined. */
1417       tvs.modtime=MAX(interpret_long_date(pdata+16),
1418                       interpret_long_date(pdata+24));
1419
1420 #if 0 /* Needs more testing... */
1421       /* Test from Luke to prevent Win95 from
1422          setting incorrect values here.
1423        */
1424       if (tvs.actime < tvs.modtime)
1425         return(ERROR(ERRDOS,ERRnoaccess));
1426 #endif /* Needs more testing... */
1427
1428       /* attributes */
1429       mode = IVAL(pdata,32);
1430       break;
1431     }
1432
1433     case SMB_SET_FILE_END_OF_FILE_INFO:
1434     {
1435       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1436          return(ERROR(ERRDOS,ERRunknownlevel));
1437       size = IVAL(pdata,0);
1438       break;
1439     }
1440
1441     case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1442     case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1443     default:
1444     {
1445       return(ERROR(ERRDOS,ERRunknownlevel));
1446     }
1447   }
1448
1449   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1450   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1451   DEBUG(6,("size: %x "   , size));
1452   DEBUG(6,("mode: %x\n"  , mode));
1453
1454   /* get some defaults (no modifications) if any info is zero. */
1455   if (!tvs.actime) tvs.actime = st.st_atime;
1456   if (!tvs.modtime) tvs.modtime = st.st_mtime;
1457   if (!size) size = st.st_size;
1458
1459   /* Try and set the times, size and mode of this file -
1460      if they are different from the current values
1461    */
1462   if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1463   {
1464     if(file_utime(cnum, fname, &tvs)!=0)
1465     {
1466       return(ERROR(ERRDOS,ERRnoaccess));
1467     }
1468   }
1469
1470   /* check the mode isn't different, before changing it */
1471   if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1472   {
1473     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1474     return(ERROR(ERRDOS,ERRnoaccess));
1475   }
1476
1477   if(size != st.st_size)
1478   {
1479     if (fd == -1)
1480     {
1481       fd = sys_open(fname,O_RDWR,0);
1482       if (fd == -1)
1483       {
1484         return(ERROR(ERRDOS,ERRbadpath));
1485       }
1486       set_filelen(fd, size);
1487       close(fd);
1488     }
1489     else
1490     {
1491       set_filelen(fd, size);
1492     }
1493   }
1494
1495   SSVAL(params,0,0);
1496
1497   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1498   
1499   return(-1);
1500 }
1501
1502 /****************************************************************************
1503   reply to a TRANS2_MKDIR (make directory with extended attributes).
1504 ****************************************************************************/
1505 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1506                         int cnum, char **pparams, char **ppdata)
1507 {
1508   char *params = *pparams;
1509   pstring directory;
1510   int ret = -1;
1511   BOOL bad_path = False;
1512
1513   if (!CAN_WRITE(cnum))
1514     return(ERROR(ERRSRV,ERRaccess));
1515
1516   pstrcpy(directory, &params[4]);
1517
1518   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1519
1520   unix_convert(directory,cnum,0,&bad_path);
1521   if (check_name(directory,cnum))
1522     ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1523   
1524   if(ret < 0)
1525     {
1526       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1527       if((errno == ENOENT) && bad_path)
1528       {
1529         unix_ERR_class = ERRDOS;
1530         unix_ERR_code = ERRbadpath;
1531       }
1532       return(UNIXERROR(ERRDOS,ERRnoaccess));
1533     }
1534
1535   /* Realloc the parameter and data sizes */
1536   params = *pparams = Realloc(*pparams,2);
1537   if(params == NULL)
1538     return(ERROR(ERRDOS,ERRnomem));
1539
1540   SSVAL(params,0,0);
1541
1542   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1543   
1544   return(-1);
1545 }
1546
1547 /****************************************************************************
1548   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1549   We don't actually do this - we just send a null response.
1550 ****************************************************************************/
1551 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1552                         int cnum, char **pparams, char **ppdata)
1553 {
1554   static uint16 fnf_handle = 257;
1555   char *params = *pparams;
1556   uint16 info_level = SVAL(params,4);
1557
1558   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1559
1560   switch (info_level) 
1561     {
1562     case 1:
1563     case 2:
1564       break;
1565     default:
1566       return(ERROR(ERRDOS,ERRunknownlevel));
1567     }
1568
1569   /* Realloc the parameter and data sizes */
1570   params = *pparams = Realloc(*pparams,6);
1571   if(params == NULL)
1572     return(ERROR(ERRDOS,ERRnomem));
1573
1574   SSVAL(params,0,fnf_handle);
1575   SSVAL(params,2,0); /* No changes */
1576   SSVAL(params,4,0); /* No EA errors */
1577
1578   fnf_handle++;
1579
1580   if(fnf_handle == 0)
1581     fnf_handle = 257;
1582
1583   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1584   
1585   return(-1);
1586 }
1587
1588 /****************************************************************************
1589   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
1590   changes). Currently this does nothing.
1591 ****************************************************************************/
1592 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1593                         int cnum, char **pparams, char **ppdata)
1594 {
1595   char *params = *pparams;
1596
1597   DEBUG(3,("call_trans2findnotifynext\n"));
1598
1599   /* Realloc the parameter and data sizes */
1600   params = *pparams = Realloc(*pparams,4);
1601   if(params == NULL)
1602     return(ERROR(ERRDOS,ERRnomem));
1603
1604   SSVAL(params,0,0); /* No changes */
1605   SSVAL(params,2,0); /* No EA errors */
1606
1607   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1608   
1609   return(-1);
1610 }
1611
1612 /****************************************************************************
1613   reply to a SMBfindclose (stop trans2 directory search)
1614 ****************************************************************************/
1615 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1616 {
1617   int cnum;
1618   int outsize = 0;
1619   int16 dptr_num=SVALS(inbuf,smb_vwv0);
1620
1621   cnum = SVAL(inbuf,smb_tid);
1622
1623   DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1624
1625   dptr_close(dptr_num);
1626
1627   outsize = set_message(outbuf,0,0,True);
1628
1629   DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1630
1631   return(outsize);
1632 }
1633
1634 /****************************************************************************
1635   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1636 ****************************************************************************/
1637 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1638 {
1639   int cnum;
1640   int outsize = 0;
1641   int dptr_num= -1;
1642
1643   cnum = SVAL(inbuf,smb_tid);
1644   dptr_num = SVAL(inbuf,smb_vwv0);
1645
1646   DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1647
1648   /* We never give out valid handles for a 
1649      findnotifyfirst - so any dptr_num is ok here. 
1650      Just ignore it. */
1651
1652   outsize = set_message(outbuf,0,0,True);
1653
1654   DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1655
1656   return(outsize);
1657 }
1658
1659
1660 /****************************************************************************
1661   reply to a SMBtranss2 - just ignore it!
1662 ****************************************************************************/
1663 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1664 {
1665   DEBUG(4,("Ignoring transs2 of length %d\n",length));
1666   return(-1);
1667 }
1668
1669 /****************************************************************************
1670   reply to a SMBtrans2
1671 ****************************************************************************/
1672 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1673 {
1674   int outsize = 0;
1675   int cnum = SVAL(inbuf,smb_tid);
1676   unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1677   unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1678 #if 0
1679   unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1680   unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1681   unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1682   BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1683   BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1684   int32 timeout = IVALS(inbuf,smb_timeout);
1685 #endif
1686   unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1687   unsigned int tran_call = SVAL(inbuf, smb_setup0);
1688   char *params = NULL, *data = NULL;
1689   int num_params, num_params_sofar, num_data, num_data_sofar;
1690
1691   outsize = set_message(outbuf,0,0,True);
1692
1693   /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1694      is so as a sanity check */
1695   if(suwcnt != 1 )
1696     {
1697       DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1698       return(ERROR(ERRSRV,ERRerror));
1699     }
1700     
1701   /* Allocate the space for the maximum needed parameters and data */
1702   if (total_params > 0)
1703     params = (char *)malloc(total_params);
1704   if (total_data > 0)
1705     data = (char *)malloc(total_data);
1706   
1707   if ((total_params && !params)  || (total_data && !data))
1708     {
1709       DEBUG(2,("Out of memory in reply_trans2\n"));
1710       return(ERROR(ERRDOS,ERRnomem));
1711     }
1712
1713   /* Copy the param and data bytes sent with this request into
1714      the params buffer */
1715   num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1716   num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1717
1718   if (num_params > total_params || num_data > total_data)
1719           exit_server("invalid params in reply_trans2");
1720
1721   memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1722   memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1723
1724   if(num_data_sofar < total_data || num_params_sofar < total_params)
1725     {
1726     /* We need to send an interim response then receive the rest
1727        of the parameter/data bytes */
1728       outsize = set_message(outbuf,0,0,True);
1729       send_smb(Client,outbuf);
1730
1731       while( num_data_sofar < total_data || num_params_sofar < total_params)
1732         {
1733           BOOL ret;
1734
1735           ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1736                              SMB_SECONDARY_WAIT);
1737
1738           if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret)
1739             {
1740               outsize = set_message(outbuf,0,0,True);
1741               if(ret)
1742                 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1743               else
1744                 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1745                          (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1746               free(params);
1747               free(data);
1748               return(ERROR(ERRSRV,ERRerror));
1749             }
1750       
1751           /* Revise total_params and total_data in case they have changed downwards */
1752           total_params = SVAL(inbuf, smb_tpscnt);
1753           total_data = SVAL(inbuf, smb_tdscnt);
1754           num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1755           num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1756           if (num_params_sofar > total_params || num_data_sofar > total_data)
1757                   exit_server("data overflow in trans2");
1758
1759           memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
1760                  smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1761           memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1762                  smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1763         }
1764     }
1765
1766   if (Protocol >= PROTOCOL_NT1) {
1767     uint16 flg2 = SVAL(outbuf,smb_flg2);
1768     SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1769   }
1770
1771   /* Now we must call the relevant TRANS2 function */
1772   switch(tran_call) 
1773     {
1774     case TRANSACT2_OPEN:
1775       outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, &params, &data);
1776       break;
1777     case TRANSACT2_FINDFIRST:
1778       outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, &params, &data);
1779       break;
1780     case TRANSACT2_FINDNEXT:
1781       outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1782       break;
1783     case TRANSACT2_QFSINFO:
1784       outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1785       break;
1786     case TRANSACT2_SETFSINFO:
1787       outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1788       break;
1789     case TRANSACT2_QPATHINFO:
1790     case TRANSACT2_QFILEINFO:
1791       outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1792       break;
1793     case TRANSACT2_SETPATHINFO:
1794     case TRANSACT2_SETFILEINFO:
1795       outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1796       break;
1797     case TRANSACT2_FINDNOTIFYFIRST:
1798       outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1799       break;
1800     case TRANSACT2_FINDNOTIFYNEXT:
1801       outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1802       break;
1803     case TRANSACT2_MKDIR:
1804       outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1805       break;
1806     default:
1807       /* Error in request */
1808       DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1809       if(params)
1810         free(params);
1811       if(data)
1812         free(data);
1813       return (ERROR(ERRSRV,ERRerror));
1814     }
1815
1816   /* As we do not know how many data packets will need to be
1817      returned here the various call_trans2xxxx calls
1818      must send their own. Thus a call_trans2xxx routine only
1819      returns a value other than -1 when it wants to send
1820      an error packet. 
1821   */
1822
1823   if(params)
1824     free(params);
1825   if(data)
1826     free(data);
1827   return outsize; /* If a correct response was needed the call_trans2xxx 
1828                      calls have already sent it. If outsize != -1 then it is
1829                      returning an error packet. */
1830 }