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