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