nmblookup.c: Added -A ability to do status on ip address.
[kai/samba.git] / source3 / smbd / trans2.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB transaction2 handling
5    Copyright (C) Jeremy Allison 1994-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
611 #if 0
612     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
613     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
614        (get_remote_arch() == RA_WINNT))
615     {
616       unix_ERR_class = ERRDOS;
617       unix_ERR_code = ERRbaddirectory;
618     }
619 #endif 
620
621     return(ERROR(ERRDOS,ERRbadpath));
622   }
623
624   p = strrchr(directory,'/');
625   if(p == NULL) {
626     strcpy(mask,directory);
627     strcpy(directory,"./");
628   } else {
629     strcpy(mask,p+1);
630     *p = 0;
631   }
632
633   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
634
635   pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
636   if(!*ppdata)
637     return(ERROR(ERRDOS,ERRnomem));
638   bzero(pdata,max_data_bytes);
639
640   /* Realloc the params space */
641   params = *pparams = Realloc(*pparams, 10);
642   if(params == NULL)
643     return(ERROR(ERRDOS,ERRnomem));
644
645   dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
646   if (dptr_num < 0)
647     {
648       if(dptr_num == -2)
649       {
650         if((errno == ENOENT) && bad_path)
651         {
652           unix_ERR_class = ERRDOS;
653           unix_ERR_code = ERRbadpath;
654         }
655
656 #if 0
657         /* Ugly - NT specific hack - maybe not needed ? (JRA) */
658         if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
659            (get_remote_arch() == RA_WINNT))
660         {
661           unix_ERR_class = ERRDOS;
662           unix_ERR_code = ERRbaddirectory;
663         }
664 #endif
665
666         return (UNIXERROR(ERRDOS,ERRbadpath));
667       }
668       return(ERROR(ERRDOS,ERRbadpath));
669     }
670
671   /* convert the formatted masks */
672   {
673     p = mask;
674     while (*p) {
675       if (*p == '<') *p = '*';
676       if (*p == '>') *p = '?';
677       if (*p == '"') *p = '.';
678       p++;
679     }
680   }
681   
682   /* a special case for 16 bit apps */
683   if (strequal(mask,"????????.???")) strcpy(mask,"*");
684
685   /* handle broken clients that send us old 8.3 format */
686   string_sub(mask,"????????","*");
687   string_sub(mask,".???",".*");
688
689   /* Save the wildcard match and attribs we are using on this directory - 
690      needed as lanman2 assumes these are being saved between calls */
691
692   if(!(wcard = strdup(mask))) {
693     dptr_close(dptr_num);
694     return(ERROR(ERRDOS,ERRnomem));
695   }
696
697   dptr_set_wcard(dptr_num, wcard);
698   dptr_set_attr(dptr_num, dirtype);
699
700   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
701
702   /* We don't need to check for VOL here as this is returned by 
703      a different TRANS2 call. */
704   
705   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
706            Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
707   if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
708     dont_descend = True;
709     
710   p = pdata;
711   space_remaining = max_data_bytes;
712   out_of_space = False;
713
714   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
715     {
716
717       /* this is a heuristic to avoid seeking the dirptr except when 
718          absolutely necessary. It allows for a filename of about 40 chars */
719       if (space_remaining < DIRLEN_GUESS && numentries > 0)
720         {
721           out_of_space = True;
722           finished = False;
723         }
724       else
725         {
726           finished = 
727             !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
728                                    requires_resume_key,dont_descend,
729                                    &p,pdata,space_remaining, &out_of_space,
730                                    &last_name_off);
731         }
732
733       if (finished && out_of_space)
734         finished = False;
735
736       if (!finished && !out_of_space)
737         numentries++;
738       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
739     }
740   
741   /* Check if we can close the dirptr */
742   if(close_after_first || (finished && close_if_end))
743     {
744       dptr_close(dptr_num);
745       DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
746       dptr_num = -1;
747     }
748
749   /* At this point pdata points to numentries directory entries. */
750
751   /* Set up the return parameter block */
752   SSVAL(params,0,dptr_num);
753   SSVAL(params,2,numentries);
754   SSVAL(params,4,finished);
755   SSVAL(params,6,0); /* Never an EA error */
756   SSVAL(params,8,last_name_off);
757
758   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
759
760   if ((! *directory) && dptr_path(dptr_num))
761     sprintf(directory,"(%s)",dptr_path(dptr_num));
762
763   DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
764         timestring(),
765         smb_fn_name(CVAL(inbuf,smb_com)), 
766         mask,directory,cnum,dirtype,numentries));
767
768   return(-1);
769 }
770
771
772 /****************************************************************************
773   reply to a TRANS2_FINDNEXT
774 ****************************************************************************/
775 static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
776                         int cnum, char **pparams, char **ppdata)
777 {
778   /* We must be careful here that we don't return more than the
779      allowed number of data bytes. If this means returning fewer than
780      maxentries then so be it. We assume that the redirector has
781      enough room for the fixed number of parameter bytes it has
782      requested. */
783   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
784   char *params = *pparams;
785   char *pdata = *ppdata;
786   int16 dptr_num = SVAL(params,0);
787   int maxentries = SVAL(params,2);
788   uint16 info_level = SVAL(params,4);
789   uint32 resume_key = IVAL(params,6);
790   BOOL close_after_request = BITSETW(params+10,0);
791   BOOL close_if_end = BITSETW(params+10,1);
792   BOOL requires_resume_key = BITSETW(params+10,2);
793   BOOL continue_bit = BITSETW(params+10,3);
794   pstring mask;
795   pstring directory;
796   char *p;
797   uint16 dirtype;
798   int numentries = 0;
799   int i, last_name_off=0;
800   BOOL finished = False;
801   BOOL dont_descend = False;
802   BOOL out_of_space = False;
803   int space_remaining;
804
805   *mask = *directory = 0;
806
807   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",
808            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
809            requires_resume_key, resume_key, continue_bit, info_level));
810
811   switch (info_level) 
812     {
813     case 1:
814     case 2:
815     case 3:
816     case 4:
817     case SMB_FIND_FILE_DIRECTORY_INFO:
818     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
819     case SMB_FIND_FILE_NAMES_INFO:
820     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
821       break;
822     default:
823       return(ERROR(ERRDOS,ERRunknownlevel));
824     }
825
826   pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
827   if(!*ppdata)
828     return(ERROR(ERRDOS,ERRnomem));
829   bzero(pdata,max_data_bytes);
830
831   /* Realloc the params space */
832   params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
833   if(!params)
834     return(ERROR(ERRDOS,ERRnomem));
835
836   /* Check that the dptr is valid */
837   if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
838     return(ERROR(ERRDOS,ERRnofiles));
839
840   string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
841
842   /* Get the wildcard mask from the dptr */
843   if((p = dptr_wcard(dptr_num))== NULL) {
844     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
845     return (ERROR(ERRDOS,ERRnofiles));
846   }
847   strcpy(mask, p);
848   strcpy(directory,Connections[cnum].dirpath);
849
850   /* Get the attr mask from the dptr */
851   dirtype = dptr_attr(dptr_num);
852
853   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
854            dptr_num, mask, dirtype, 
855            Connections[cnum].dirptr,
856            TellDir(Connections[cnum].dirptr)));
857
858   /* We don't need to check for VOL here as this is returned by 
859      a different TRANS2 call. */
860
861   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
862   if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
863     dont_descend = True;
864     
865   p = pdata;
866   space_remaining = max_data_bytes;
867   out_of_space = False;
868
869   /* If we have a resume key - seek to the correct position. */
870   if(requires_resume_key && !continue_bit)
871     SeekDir(Connections[cnum].dirptr, resume_key);
872
873   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
874     {
875       /* this is a heuristic to avoid seeking the dirptr except when 
876          absolutely necessary. It allows for a filename of about 40 chars */
877       if (space_remaining < DIRLEN_GUESS && numentries > 0)
878         {
879           out_of_space = True;
880           finished = False;
881         }
882       else
883         {
884           finished = 
885             !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
886                                    requires_resume_key,dont_descend,
887                                    &p,pdata,space_remaining, &out_of_space,
888                                    &last_name_off);
889         }
890
891       if (finished && out_of_space)
892         finished = False;
893
894       if (!finished && !out_of_space)
895         numentries++;
896       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
897     }
898   
899   /* Check if we can close the dirptr */
900   if(close_after_request || (finished && close_if_end))
901     {
902       dptr_close(dptr_num); /* This frees up the saved mask */
903       DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
904       dptr_num = -1;
905     }
906
907
908   /* Set up the return parameter block */
909   SSVAL(params,0,numentries);
910   SSVAL(params,2,finished);
911   SSVAL(params,4,0); /* Never an EA error */
912   SSVAL(params,6,last_name_off);
913
914   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
915
916   if ((! *directory) && dptr_path(dptr_num))
917     sprintf(directory,"(%s)",dptr_path(dptr_num));
918
919   DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
920            timestring(),
921            smb_fn_name(CVAL(inbuf,smb_com)), 
922            mask,directory,cnum,dirtype,numentries));
923
924   return(-1);
925 }
926
927 /****************************************************************************
928   reply to a TRANS2_QFSINFO (query filesystem info)
929 ****************************************************************************/
930 static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
931                         int cnum, char **pparams, char **ppdata)
932 {
933   char *pdata = *ppdata;
934   char *params = *pparams;
935   uint16 info_level = SVAL(params,0);
936   int data_len;
937   struct stat st;
938   char *vname = volume_label(SNUM(cnum));
939   
940   DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
941
942   if(sys_stat(".",&st)!=0) {
943     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
944     return (ERROR(ERRSRV,ERRinvdevice));
945   }
946
947   pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
948
949   switch (info_level) 
950     {
951     case 1:
952       {
953         int dfree,dsize,bsize;
954         data_len = 18;
955         sys_disk_free(".",&bsize,&dfree,&dsize);        
956         SIVAL(pdata,l1_idFileSystem,st.st_dev);
957         SIVAL(pdata,l1_cSectorUnit,bsize/512);
958         SIVAL(pdata,l1_cUnit,dsize);
959         SIVAL(pdata,l1_cUnitAvail,dfree);
960         SSVAL(pdata,l1_cbSector,512);
961         DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
962                  bsize, st.st_dev, bsize/512, dsize, dfree, 512));
963         break;
964     }
965     case 2:
966     { 
967       /* Return volume name */
968       int volname_len = MIN(strlen(vname),11);
969       data_len = l2_vol_szVolLabel + volname_len + 1;
970       put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
971       SCVAL(pdata,l2_vol_cch,volname_len);
972       StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
973       DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
974                pdata+l2_vol_szVolLabel));
975       break;
976     }
977     case SMB_QUERY_FS_ATTRIBUTE_INFO:
978       data_len = 12 + 2*strlen(FSTYPE_STRING);
979       SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
980       SIVAL(pdata,4,128); /* Max filename component length */
981       SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
982       PutUniCode(pdata+12,FSTYPE_STRING);
983       break;
984     case SMB_QUERY_FS_LABEL_INFO:
985       data_len = 4 + strlen(vname);
986       SIVAL(pdata,0,strlen(vname));
987       strcpy(pdata+4,vname);      
988       break;
989     case SMB_QUERY_FS_VOLUME_INFO:      
990       data_len = 18 + 2*strlen(vname);
991       SIVAL(pdata,12,2*strlen(vname));
992       PutUniCode(pdata+18,vname);      
993       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
994                vname));
995       break;
996     case SMB_QUERY_FS_SIZE_INFO:
997       {
998         int dfree,dsize,bsize;
999         data_len = 24;
1000         sys_disk_free(".",&bsize,&dfree,&dsize);        
1001         SIVAL(pdata,0,dsize);
1002         SIVAL(pdata,8,dfree);
1003         SIVAL(pdata,16,bsize/512);
1004         SIVAL(pdata,20,512);
1005       }
1006       break;
1007     case SMB_QUERY_FS_DEVICE_INFO:
1008       data_len = 8;
1009       SIVAL(pdata,0,0); /* dev type */
1010       SIVAL(pdata,4,0); /* characteristics */
1011       break;
1012     default:
1013       return(ERROR(ERRDOS,ERRunknownlevel));
1014     }
1015
1016
1017   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1018
1019   DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
1020
1021   return -1;
1022 }
1023
1024 /****************************************************************************
1025   reply to a TRANS2_SETFSINFO (set filesystem info)
1026 ****************************************************************************/
1027 static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
1028                         int cnum, char **pparams, char **ppdata)
1029 {
1030   /* Just say yes we did it - there is nothing that
1031      can be set here so it doesn't matter. */
1032   int outsize;
1033   DEBUG(3,("call_trans2setfsinfo\n"));
1034
1035   if (!CAN_WRITE(cnum))
1036     return(ERROR(ERRSRV,ERRaccess));
1037
1038   outsize = set_message(outbuf,10,0,True);
1039
1040   return outsize;
1041 }
1042
1043 /****************************************************************************
1044   reply to a TRANS2_QFILEINFO (query file info by fileid)
1045 ****************************************************************************/
1046 static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, 
1047                                     int bufsize,int cnum,
1048                                     char **pparams,char **ppdata,
1049                                     int total_data)
1050 {
1051   char *params = *pparams;
1052   char *pdata = *ppdata;
1053   uint16 tran_call = SVAL(inbuf, smb_setup0);
1054   uint16 info_level;
1055   int mode=0;
1056   int size=0;
1057   unsigned int data_size;
1058   struct stat sbuf;
1059   pstring fname1;
1060   char *fname;
1061   char *p;
1062   int l,pos;
1063   BOOL bad_path = False;
1064
1065   if (tran_call == TRANSACT2_QFILEINFO) {
1066     int16 fnum = SVALS(params,0);
1067     info_level = SVAL(params,2);
1068
1069     CHECK_FNUM(fnum,cnum);
1070     CHECK_ERROR(fnum);
1071
1072     fname = Files[fnum].name;
1073     if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1074       DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1075       return(UNIXERROR(ERRDOS,ERRbadfid));
1076     }
1077     pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1078   } else {
1079     /* qpathinfo */
1080     info_level = SVAL(params,0);
1081     fname = &fname1[0];
1082     pstrcpy(fname,&params[6]);
1083     unix_convert(fname,cnum,0,&bad_path);
1084     if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
1085       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1086       if((errno == ENOENT) && bad_path)
1087       {
1088         unix_ERR_class = ERRDOS;
1089         unix_ERR_code = ERRbadpath;
1090       }
1091       return(UNIXERROR(ERRDOS,ERRbadpath));
1092     }
1093     pos = 0;
1094   }
1095
1096
1097   DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1098            fname,info_level,tran_call,total_data));
1099
1100   p = strrchr(fname,'/'); 
1101   if (!p) 
1102     p = fname;
1103   else
1104     p++;
1105   l = strlen(p);  
1106   mode = dos_mode(cnum,fname,&sbuf);
1107   size = sbuf.st_size;
1108   if (mode & aDIR) size = 0;
1109   
1110   params = *pparams = Realloc(*pparams,2); bzero(params,2);
1111   data_size = 1024;
1112   pdata = *ppdata = Realloc(*ppdata, data_size); 
1113
1114   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1115     /* uggh, EAs for OS2 */
1116     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1117     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1118   }
1119
1120   bzero(pdata,data_size);
1121
1122   switch (info_level) 
1123     {
1124     case SMB_INFO_STANDARD:
1125     case SMB_INFO_QUERY_EA_SIZE:
1126       data_size = (info_level==1?22:26);
1127       put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
1128       put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
1129       put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1130       SIVAL(pdata,l1_cbFile,size);
1131       SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1132       SSVAL(pdata,l1_attrFile,mode);
1133       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1134       break;
1135
1136     case SMB_INFO_QUERY_EAS_FROM_LIST:
1137       data_size = 24;
1138       put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
1139       put_dos_date2(pdata,4,sbuf.st_atime);
1140       put_dos_date2(pdata,8,sbuf.st_mtime);
1141       SIVAL(pdata,12,size);
1142       SIVAL(pdata,16,ROUNDUP(size,1024));
1143       SIVAL(pdata,20,mode);
1144       break;
1145
1146     case SMB_INFO_QUERY_ALL_EAS:
1147       data_size = 4;
1148       SIVAL(pdata,0,data_size);
1149       break;
1150
1151     case 6:
1152       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
1153
1154     case SMB_QUERY_FILE_BASIC_INFO:
1155       data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1156       put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1157       put_long_date(pdata+8,sbuf.st_atime); /* access time */
1158       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1159       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1160       SIVAL(pdata,32,mode);
1161
1162       DEBUG(5,("SMB_QFBI - "));
1163       DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
1164       DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1165       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1166       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1167       DEBUG(5,("mode: %x\n", mode));
1168
1169       break;
1170
1171     case SMB_QUERY_FILE_STANDARD_INFO:
1172       data_size = 22;
1173       SIVAL(pdata,0,size);
1174       SIVAL(pdata,8,size);
1175       SIVAL(pdata,16,sbuf.st_nlink);
1176       CVAL(pdata,20) = 0;
1177       CVAL(pdata,21) = (mode&aDIR)?1:0;
1178       break;
1179
1180     case SMB_QUERY_FILE_EA_INFO:
1181       data_size = 4;
1182       break;
1183
1184     /* Get the 8.3 name - used if NT SMB was negotiated. */
1185     case SMB_QUERY_FILE_ALT_NAME_INFO:
1186       {
1187         pstring short_name;
1188         pstrcpy(short_name,fname);
1189         /* Mangle if not already 8.3 */
1190         if(!is_8_3(short_name, True))
1191         {
1192           if(!name_map_mangle(short_name,True,SNUM(cnum)))
1193             *short_name = '\0';
1194         }
1195         strncpy(pdata + 4,short_name,12);
1196         (pdata + 4)[12] = 0;
1197         strupper(pdata + 4);
1198         l = strlen(pdata + 4);
1199         data_size = 4 + l;
1200         SIVAL(pdata,0,l);
1201       }
1202       break;
1203
1204     case SMB_QUERY_FILE_NAME_INFO:
1205       data_size = 4 + l;
1206       SIVAL(pdata,0,l);
1207       pstrcpy(pdata+4,fname);
1208       break;
1209
1210     case SMB_QUERY_FILE_ALLOCATION_INFO:
1211     case SMB_QUERY_FILE_END_OF_FILEINFO:
1212       data_size = 8;
1213       SIVAL(pdata,0,size);
1214       break;
1215
1216     case SMB_QUERY_FILE_ALL_INFO:
1217       put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
1218       put_long_date(pdata+8,sbuf.st_atime); /* access time */
1219       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1220       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1221       SIVAL(pdata,32,mode);
1222       pdata += 40;
1223       SIVAL(pdata,0,size);
1224       SIVAL(pdata,8,size);
1225       SIVAL(pdata,16,sbuf.st_nlink);
1226       CVAL(pdata,20) = 0;
1227       CVAL(pdata,21) = (mode&aDIR)?1:0;
1228       pdata += 24;
1229       pdata += 8; /* index number */
1230       pdata += 4; /* EA info */
1231       if (mode & aRONLY)
1232         SIVAL(pdata,0,0xA9);
1233       else
1234         SIVAL(pdata,0,0xd01BF);
1235       pdata += 4;
1236       SIVAL(pdata,0,pos); /* current offset */
1237       pdata += 8;
1238       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1239       pdata += 4;
1240       pdata += 4; /* alignment */
1241       SIVAL(pdata,0,l);
1242       pstrcpy(pdata+4,fname);
1243       pdata += 4 + l;
1244       data_size = PTR_DIFF(pdata,(*ppdata));
1245       break;
1246
1247     case SMB_QUERY_FILE_STREAM_INFO:
1248       data_size = 24 + l;
1249       SIVAL(pdata,0,pos);
1250       SIVAL(pdata,4,size);
1251       SIVAL(pdata,12,size);
1252       SIVAL(pdata,20,l);        
1253       pstrcpy(pdata+24,fname);
1254       break;
1255     default:
1256       return(ERROR(ERRDOS,ERRunknownlevel));
1257     }
1258
1259   send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1260
1261   return(-1);
1262 }
1263
1264 /****************************************************************************
1265   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1266 ****************************************************************************/
1267 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, 
1268                                       int bufsize, int cnum, char **pparams, 
1269                                       char **ppdata, int total_data)
1270 {
1271   char *params = *pparams;
1272   char *pdata = *ppdata;
1273   uint16 tran_call = SVAL(inbuf, smb_setup0);
1274   uint16 info_level;
1275   int mode=0;
1276   int size=0;
1277   struct utimbuf tvs;
1278   struct stat st;
1279   pstring fname1;
1280   char *fname;
1281   int fd = -1;
1282   BOOL bad_path = False;
1283
1284   if (!CAN_WRITE(cnum))
1285     return(ERROR(ERRSRV,ERRaccess));
1286
1287   if (tran_call == TRANSACT2_SETFILEINFO) {
1288     int16 fnum = SVALS(params,0);
1289     info_level = SVAL(params,2);    
1290
1291     CHECK_FNUM(fnum,cnum);
1292     CHECK_ERROR(fnum);
1293
1294     fname = Files[fnum].name;
1295     fd = Files[fnum].fd_ptr->fd;
1296
1297     if(fstat(fd,&st)!=0) {
1298       DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1299       return(ERROR(ERRDOS,ERRbadpath));
1300     }
1301   } else {
1302     /* set path info */
1303     info_level = SVAL(params,0);    
1304     fname = fname1;
1305     pstrcpy(fname,&params[6]);
1306     unix_convert(fname,cnum,0,&bad_path);
1307     if(!check_name(fname, cnum))
1308     {
1309       if((errno == ENOENT) && bad_path)
1310       {
1311         unix_ERR_class = ERRDOS;
1312         unix_ERR_code = ERRbadpath;
1313       }
1314       return(UNIXERROR(ERRDOS,ERRbadpath));
1315     }
1316  
1317     if(sys_stat(fname,&st)!=0) {
1318       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1319       if((errno == ENOENT) && bad_path)
1320       {
1321         unix_ERR_class = ERRDOS;
1322         unix_ERR_code = ERRbadpath;
1323       }
1324       return(UNIXERROR(ERRDOS,ERRbadpath));
1325     }    
1326   }
1327
1328   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1329            tran_call,fname,info_level,total_data));
1330
1331   /* Realloc the parameter and data sizes */
1332   params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1333   if(params == NULL)
1334     return(ERROR(ERRDOS,ERRnomem));
1335
1336   size = st.st_size;
1337   tvs.modtime = st.st_mtime;
1338   tvs.actime = st.st_atime;
1339   mode = dos_mode(cnum,fname,&st);
1340
1341   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1342     /* uggh, EAs for OS2 */
1343     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1344     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1345   }
1346
1347   switch (info_level)
1348   {
1349     case SMB_INFO_STANDARD:
1350     case SMB_INFO_QUERY_EA_SIZE:
1351     {
1352       /* access time */
1353       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1354
1355       /* write time */
1356       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1357
1358       mode = SVAL(pdata,l1_attrFile);
1359       size = IVAL(pdata,l1_cbFile);
1360       break;
1361     }
1362
1363     /* XXXX um, i don't think this is right.
1364        it's also not in the cifs6.txt spec.
1365      */
1366     case SMB_INFO_QUERY_EAS_FROM_LIST:
1367       tvs.actime = make_unix_date2(pdata+8);
1368       tvs.modtime = make_unix_date2(pdata+12);
1369       size = IVAL(pdata,16);
1370       mode = IVAL(pdata,24);
1371       break;
1372
1373     /* XXXX nor this.  not in cifs6.txt, either. */
1374     case SMB_INFO_QUERY_ALL_EAS:
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     case SMB_SET_FILE_BASIC_INFO:
1382     {
1383       /* Ignore create time at offset pdata. */
1384
1385       /* access time */
1386       tvs.actime = interpret_long_date(pdata+8);
1387
1388       /* write time + changed time, combined. */
1389       tvs.modtime=MAX(interpret_long_date(pdata+16),
1390                       interpret_long_date(pdata+24));
1391
1392 #if 0 /* Needs more testing... */
1393       /* Test from Luke to prevent Win95 from
1394          setting incorrect values here.
1395        */
1396       if (tvs.actime < tvs.modtime)
1397         return(ERROR(ERRDOS,ERRnoaccess));
1398 #endif /* Needs more testing... */
1399
1400       /* attributes */
1401       mode = IVAL(pdata,32);
1402       break;
1403     }
1404
1405     case SMB_SET_FILE_END_OF_FILE_INFO:
1406     {
1407       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1408          return(ERROR(ERRDOS,ERRunknownlevel));
1409       size = IVAL(pdata,0);
1410       break;
1411     }
1412
1413     case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1414     case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1415     default:
1416     {
1417       return(ERROR(ERRDOS,ERRunknownlevel));
1418     }
1419   }
1420
1421   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1422   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1423   DEBUG(6,("size: %x "   , size));
1424   DEBUG(6,("mode: %x\n"  , mode));
1425
1426   /* get some defaults (no modifications) if any info is zero. */
1427   if (!tvs.actime) tvs.actime = st.st_atime;
1428   if (!tvs.modtime) tvs.modtime = st.st_mtime;
1429   if (!size) size = st.st_size;
1430
1431   /* Try and set the times, size and mode of this file -
1432      if they are different from the current values
1433    */
1434   if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1435   {
1436     if(sys_utime(fname, &tvs)!=0)
1437     {
1438       return(ERROR(ERRDOS,ERRnoaccess));
1439     }
1440   }
1441
1442   /* check the mode isn't different, before changing it */
1443   if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1444   {
1445     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1446     return(ERROR(ERRDOS,ERRnoaccess));
1447   }
1448
1449   if(size != st.st_size)
1450   {
1451     if (fd == -1)
1452     {
1453       fd = sys_open(fname,O_RDWR,0);
1454       if (fd == -1)
1455       {
1456         return(ERROR(ERRDOS,ERRbadpath));
1457       }
1458       set_filelen(fd, size);
1459       close(fd);
1460     }
1461     else
1462     {
1463       set_filelen(fd, size);
1464     }
1465   }
1466
1467   SSVAL(params,0,0);
1468
1469   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1470   
1471   return(-1);
1472 }
1473
1474 /****************************************************************************
1475   reply to a TRANS2_MKDIR (make directory with extended attributes).
1476 ****************************************************************************/
1477 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1478                         int cnum, char **pparams, char **ppdata)
1479 {
1480   char *params = *pparams;
1481   pstring directory;
1482   int ret = -1;
1483   BOOL bad_path = False;
1484
1485   if (!CAN_WRITE(cnum))
1486     return(ERROR(ERRSRV,ERRaccess));
1487
1488   pstrcpy(directory, &params[4]);
1489
1490   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1491
1492   unix_convert(directory,cnum,0,&bad_path);
1493   if (check_name(directory,cnum))
1494     ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1495   
1496   if(ret < 0)
1497     {
1498       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1499       if((errno == ENOENT) && bad_path)
1500       {
1501         unix_ERR_class = ERRDOS;
1502         unix_ERR_code = ERRbadpath;
1503       }
1504       return(UNIXERROR(ERRDOS,ERRnoaccess));
1505     }
1506
1507   /* Realloc the parameter and data sizes */
1508   params = *pparams = Realloc(*pparams,2);
1509   if(params == NULL)
1510     return(ERROR(ERRDOS,ERRnomem));
1511
1512   SSVAL(params,0,0);
1513
1514   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1515   
1516   return(-1);
1517 }
1518
1519 /****************************************************************************
1520   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1521   We don't actually do this - we just send a null response.
1522 ****************************************************************************/
1523 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1524                         int cnum, char **pparams, char **ppdata)
1525 {
1526   static uint16 fnf_handle = 257;
1527   char *params = *pparams;
1528   uint16 info_level = SVAL(params,4);
1529
1530   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1531
1532   switch (info_level) 
1533     {
1534     case 1:
1535     case 2:
1536       break;
1537     default:
1538       return(ERROR(ERRDOS,ERRunknownlevel));
1539     }
1540
1541   /* Realloc the parameter and data sizes */
1542   params = *pparams = Realloc(*pparams,6);
1543   if(params == NULL)
1544     return(ERROR(ERRDOS,ERRnomem));
1545
1546   SSVAL(params,0,fnf_handle);
1547   SSVAL(params,2,0); /* No changes */
1548   SSVAL(params,4,0); /* No EA errors */
1549
1550   fnf_handle++;
1551
1552   if(fnf_handle == 0)
1553     fnf_handle = 257;
1554
1555   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1556   
1557   return(-1);
1558 }
1559
1560 /****************************************************************************
1561   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
1562   changes). Currently this does nothing.
1563 ****************************************************************************/
1564 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1565                         int cnum, char **pparams, char **ppdata)
1566 {
1567   char *params = *pparams;
1568
1569   DEBUG(3,("call_trans2findnotifynext\n"));
1570
1571   /* Realloc the parameter and data sizes */
1572   params = *pparams = Realloc(*pparams,4);
1573   if(params == NULL)
1574     return(ERROR(ERRDOS,ERRnomem));
1575
1576   SSVAL(params,0,0); /* No changes */
1577   SSVAL(params,2,0); /* No EA errors */
1578
1579   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1580   
1581   return(-1);
1582 }
1583
1584 /****************************************************************************
1585   reply to a SMBfindclose (stop trans2 directory search)
1586 ****************************************************************************/
1587 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1588 {
1589   int cnum;
1590   int outsize = 0;
1591   int16 dptr_num=SVALS(inbuf,smb_vwv0);
1592
1593   cnum = SVAL(inbuf,smb_tid);
1594
1595   DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1596
1597   dptr_close(dptr_num);
1598
1599   outsize = set_message(outbuf,0,0,True);
1600
1601   DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1602
1603   return(outsize);
1604 }
1605
1606 /****************************************************************************
1607   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1608 ****************************************************************************/
1609 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1610 {
1611   int cnum;
1612   int outsize = 0;
1613   int dptr_num= -1;
1614
1615   cnum = SVAL(inbuf,smb_tid);
1616   dptr_num = SVAL(inbuf,smb_vwv0);
1617
1618   DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1619
1620   /* We never give out valid handles for a 
1621      findnotifyfirst - so any dptr_num is ok here. 
1622      Just ignore it. */
1623
1624   outsize = set_message(outbuf,0,0,True);
1625
1626   DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1627
1628   return(outsize);
1629 }
1630
1631
1632 /****************************************************************************
1633   reply to a SMBtranss2 - just ignore it!
1634 ****************************************************************************/
1635 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1636 {
1637   DEBUG(4,("Ignoring transs2 of length %d\n",length));
1638   return(-1);
1639 }
1640
1641 /****************************************************************************
1642   reply to a SMBtrans2
1643 ****************************************************************************/
1644 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1645 {
1646   int outsize = 0;
1647   int cnum = SVAL(inbuf,smb_tid);
1648   unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1649   unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1650 #if 0
1651   unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1652   unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1653   unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1654   BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1655   BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1656   int32 timeout = IVALS(inbuf,smb_timeout);
1657 #endif
1658   unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1659   unsigned int tran_call = SVAL(inbuf, smb_setup0);
1660   char *params = NULL, *data = NULL;
1661   int num_params, num_params_sofar, num_data, num_data_sofar;
1662
1663   outsize = set_message(outbuf,0,0,True);
1664
1665   /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1666      is so as a sanity check */
1667   if(suwcnt != 1 )
1668     {
1669       DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1670       return(ERROR(ERRSRV,ERRerror));
1671     }
1672     
1673   /* Allocate the space for the maximum needed parameters and data */
1674   if (total_params > 0)
1675     params = (char *)malloc(total_params);
1676   if (total_data > 0)
1677     data = (char *)malloc(total_data);
1678   
1679   if ((total_params && !params)  || (total_data && !data))
1680     {
1681       DEBUG(2,("Out of memory in reply_trans2\n"));
1682       return(ERROR(ERRDOS,ERRnomem));
1683     }
1684
1685   /* Copy the param and data bytes sent with this request into
1686      the params buffer */
1687   num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1688   num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1689
1690   if (num_params > total_params || num_data > total_data)
1691           exit_server("invalid params in reply_trans2");
1692
1693   memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1694   memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1695
1696   if(num_data_sofar < total_data || num_params_sofar < total_params)
1697     {
1698     /* We need to send an interim response then receive the rest
1699        of the parameter/data bytes */
1700       outsize = set_message(outbuf,0,0,True);
1701       send_smb(Client,outbuf);
1702
1703       while( num_data_sofar < total_data || num_params_sofar < total_params)
1704         {
1705           if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
1706              CVAL(inbuf, smb_com) != SMBtranss2)
1707             {
1708               outsize = set_message(outbuf,0,0,True);
1709               DEBUG(2,("Invalid secondary trans2 packet\n"));
1710               free(params);
1711               free(data);
1712               return(ERROR(ERRSRV,ERRerror));
1713             }
1714       
1715           /* Revise total_params and total_data in case they have changed downwards */
1716           total_params = SVAL(inbuf, smb_tpscnt);
1717           total_data = SVAL(inbuf, smb_tdscnt);
1718           num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1719           num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1720           if (num_params_sofar > total_params || num_data_sofar > total_data)
1721                   exit_server("data overflow in trans2");
1722
1723           memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
1724                  smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1725           memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1726                  smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1727         }
1728     }
1729
1730   if (Protocol >= PROTOCOL_NT1) {
1731     uint16 flg2 = SVAL(outbuf,smb_flg2);
1732     SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1733   }
1734
1735   /* Now we must call the relevant TRANS2 function */
1736   switch(tran_call) 
1737     {
1738     case TRANSACT2_OPEN:
1739       outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, &params, &data);
1740       break;
1741     case TRANSACT2_FINDFIRST:
1742       outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, &params, &data);
1743       break;
1744     case TRANSACT2_FINDNEXT:
1745       outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1746       break;
1747     case TRANSACT2_QFSINFO:
1748       outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1749       break;
1750     case TRANSACT2_SETFSINFO:
1751       outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1752       break;
1753     case TRANSACT2_QPATHINFO:
1754     case TRANSACT2_QFILEINFO:
1755       outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1756       break;
1757     case TRANSACT2_SETPATHINFO:
1758     case TRANSACT2_SETFILEINFO:
1759       outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1760       break;
1761     case TRANSACT2_FINDNOTIFYFIRST:
1762       outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1763       break;
1764     case TRANSACT2_FINDNOTIFYNEXT:
1765       outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1766       break;
1767     case TRANSACT2_MKDIR:
1768       outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1769       break;
1770     default:
1771       /* Error in request */
1772       DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1773       if(params)
1774         free(params);
1775       if(data)
1776         free(data);
1777       return (ERROR(ERRSRV,ERRerror));
1778     }
1779
1780   /* As we do not know how many data packets will need to be
1781      returned here the various call_trans2xxxx calls
1782      must send their own. Thus a call_trans2xxx routine only
1783      returns a value other than -1 when it wants to send
1784      an error packet. 
1785   */
1786
1787   if(params)
1788     free(params);
1789   if(data)
1790     free(data);
1791   return outsize; /* If a correct response was needed the call_trans2xxx 
1792                      calls have already sent it. If outsize != -1 then it is
1793                      returning an error packet. */
1794 }