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