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