always align both the parameter and data bytes on a 4 byte boundary in
[abartlet/samba.git/.git] / source3 / smbd / trans2.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB transaction2 handling
5    Copyright (C) Jeremy Allison 1994-1998
6
7    Extensively modified by Andrew Tridgell, 1995
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "trans2.h"
26
27 extern int DEBUGLEVEL;
28 extern int Protocol;
29 extern connection_struct Connections[];
30 extern files_struct Files[];
31 extern BOOL case_sensitive;
32 extern int Client;
33 extern int oplock_sock;
34 extern int smb_read_error;
35
36 /****************************************************************************
37   Send the required number of replies back.
38   We assume all fields other than the data fields are
39   set correctly for the type of call.
40   HACK ! Always assumes smb_setup field is zero.
41 ****************************************************************************/
42 static int send_trans2_replies(char *outbuf, int bufsize, char *params, 
43                          int paramsize, char *pdata, int datasize)
44 {
45   /* As we are using a protocol > LANMAN1 then the max_send
46      variable must have been set in the sessetupX call.
47      This takes precedence over the max_xmit field in the
48      global struct. These different max_xmit variables should
49      be merged as this is now too confusing */
50
51   extern int max_send;
52   int data_to_send = datasize;
53   int params_to_send = paramsize;
54   int useable_space;
55   char *pp = params;
56   char *pd = pdata;
57   int params_sent_thistime, data_sent_thistime, total_sent_thistime;
58   int alignment_offset = 3;
59   int data_alignment_offset = 0;
60
61   /* Initially set the wcnt area to be 10 - this is true for all
62      trans2 replies */
63   set_message(outbuf,10,0,True);
64
65   /* If there genuinely are no parameters or data to send just send
66      the empty packet */
67   if(params_to_send == 0 && data_to_send == 0)
68     {
69       send_smb(Client,outbuf);
70       return 0;
71     }
72
73   /* when sending params and data ensure that both are nicely aligned */
74   if ((params_to_send % 4) != 0)
75           data_alignment_offset = 4 - (params_to_send % 4);
76
77   /* Space is bufsize minus Netbios over TCP header minus SMB header */
78   /* The alignment_offset is to align the param bytes on an even byte
79      boundary. NT 4.0 Beta needs this to work correctly. */
80   useable_space = bufsize - ((smb_buf(outbuf)+
81                               alignment_offset+data_alignment_offset) - 
82                              outbuf);
83
84   /* useable_space can never be more than max_send minus the
85      alignment offset. */
86   useable_space = MIN(useable_space, 
87                       max_send - (alignment_offset+data_alignment_offset));
88
89
90   while (params_to_send || data_to_send)
91     {
92       /* Calculate whether we will totally or partially fill this packet */
93       total_sent_thistime = params_to_send + data_to_send + 
94               alignment_offset + data_alignment_offset;
95       /* We can never send more than useable_space */
96       total_sent_thistime = MIN(total_sent_thistime, useable_space);
97
98       set_message(outbuf, 10, total_sent_thistime, True);
99
100       /* Set total params and data to be sent */
101       SSVAL(outbuf,smb_tprcnt,paramsize);
102       SSVAL(outbuf,smb_tdrcnt,datasize);
103
104       /* Calculate how many parameters and data we can fit into
105          this packet. Parameters get precedence */
106
107       params_sent_thistime = MIN(params_to_send,useable_space);
108       data_sent_thistime = useable_space - params_sent_thistime;
109       data_sent_thistime = MIN(data_sent_thistime,data_to_send);
110
111       SSVAL(outbuf,smb_prcnt, params_sent_thistime);
112       if(params_sent_thistime == 0)
113         {
114           SSVAL(outbuf,smb_proff,0);
115           SSVAL(outbuf,smb_prdisp,0);
116         } else {
117           /* smb_proff is the offset from the start of the SMB header to the
118              parameter bytes, however the first 4 bytes of outbuf are
119              the Netbios over TCP header. Thus use smb_base() to subtract
120              them from the calculation */
121           SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
122           /* Absolute displacement of param bytes sent in this packet */
123           SSVAL(outbuf,smb_prdisp,pp - params);
124         }
125
126       SSVAL(outbuf,smb_drcnt, data_sent_thistime);
127       if(data_sent_thistime == 0)
128         {
129           SSVAL(outbuf,smb_droff,0);
130           SSVAL(outbuf,smb_drdisp, 0);
131         } else {
132           /* The offset of the data bytes is the offset of the
133              parameter bytes plus the number of parameters being sent this time */
134           SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
135                                   smb_base(outbuf)) + 
136                 params_sent_thistime + data_alignment_offset);
137           SSVAL(outbuf,smb_drdisp, pd - pdata);
138         }
139
140       /* Copy the param bytes into the packet */
141       if(params_sent_thistime)
142         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
143       /* Copy in the data bytes */
144       if(data_sent_thistime)
145         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+data_alignment_offset,pd,data_sent_thistime);
146
147       DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
148                params_sent_thistime, data_sent_thistime, useable_space));
149       DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
150                params_to_send, data_to_send, paramsize, datasize));
151
152       /* Send the packet */
153       send_smb(Client,outbuf);
154
155       pp += params_sent_thistime;
156       pd += data_sent_thistime;
157
158       params_to_send -= params_sent_thistime;
159       data_to_send -= data_sent_thistime;
160
161       /* Sanity check */
162       if(params_to_send < 0 || data_to_send < 0)
163         {
164           DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
165                    params_to_send, data_to_send));
166           return -1;
167         }
168     }
169
170   return 0;
171 }
172
173
174 /****************************************************************************
175   reply to a TRANSACT2_OPEN
176 ****************************************************************************/
177 static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, 
178                     char **pparams, char **ppdata)
179 {
180   char *params = *pparams;
181   int16 open_mode = SVAL(params, 2);
182   int16 open_attr = SVAL(params,6);
183   BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
184 #if 0
185   BOOL return_additional_info = BITSETW(params,0);
186   int16 open_sattr = SVAL(params, 4);
187   time_t open_time = make_unix_date3(params+8);
188 #endif
189   int16 open_ofun = SVAL(params,12);
190   int32 open_size = IVAL(params,14);
191   char *pname = &params[28];
192   int16 namelen = strlen(pname)+1;
193
194   pstring fname;
195   int fnum = -1;
196   int unixmode;
197   int size=0,fmode=0,mtime=0,rmode;
198   int32 inode = 0;
199   struct stat sbuf;
200   int smb_action = 0;
201   BOOL bad_path = False;
202
203   StrnCpy(fname,pname,namelen);
204
205   DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n",
206            fname,cnum,open_mode, open_attr, open_ofun, open_size));
207
208   /* XXXX we need to handle passed times, sattr and flags */
209
210   unix_convert(fname,cnum,0,&bad_path);
211     
212   fnum = find_free_file();
213   if (fnum < 0)
214     return(ERROR(ERRSRV,ERRnofids));
215
216   if (!check_name(fname,cnum))
217   {
218     if((errno == ENOENT) && bad_path)
219     {
220       unix_ERR_class = ERRDOS;
221       unix_ERR_code = ERRbadpath;
222     }
223     Files[fnum].reserved = False;
224     return(UNIXERROR(ERRDOS,ERRnoaccess));
225   }
226
227   unixmode = unix_mode(cnum,open_attr | aARCH);
228       
229       
230   open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
231                    oplock_request, &rmode,&smb_action);
232       
233   if (!Files[fnum].open)
234   {
235     if((errno == ENOENT) && bad_path)
236     {
237       unix_ERR_class = ERRDOS;
238       unix_ERR_code = ERRbadpath;
239     }
240     Files[fnum].reserved = False;
241     return(UNIXERROR(ERRDOS,ERRnoaccess));
242   }
243
244   if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
245     close_file(fnum,False);
246     return(ERROR(ERRDOS,ERRnoaccess));
247   }
248     
249   size = sbuf.st_size;
250   fmode = dos_mode(cnum,fname,&sbuf);
251   mtime = sbuf.st_mtime;
252   inode = sbuf.st_ino;
253   if (fmode & aDIR) {
254     close_file(fnum,False);
255     return(ERROR(ERRDOS,ERRnoaccess));
256   }
257
258   /* Realloc the size of parameters and data we will return */
259   params = *pparams = Realloc(*pparams, 28);
260   if(params == NULL)
261     return(ERROR(ERRDOS,ERRnomem));
262
263   bzero(params,28);
264   SSVAL(params,0,fnum);
265   SSVAL(params,2,fmode);
266   put_dos_date2(params,4, mtime);
267   SIVAL(params,8, size);
268   SSVAL(params,12,rmode);
269
270   if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
271     smb_action |= EXTENDED_OPLOCK_GRANTED;
272   }
273
274   SSVAL(params,18,smb_action);
275   SIVAL(params,20,inode);
276  
277   /* Send the required number of replies */
278   send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
279
280   return -1;
281 }
282
283 /****************************************************************************
284   get a level dependent lanman2 dir entry.
285 ****************************************************************************/
286 static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
287                                  int requires_resume_key,
288                                  BOOL dont_descend,char **ppdata, 
289                                  char *base_data, int space_remaining, 
290                                  BOOL *out_of_space,
291                                  int *last_name_off)
292 {
293   char *dname;
294   BOOL found = False;
295   struct stat sbuf;
296   pstring mask;
297   pstring pathreal;
298   pstring fname;
299   BOOL matched;
300   char *p, *pdata = *ppdata;
301   int reskey=0, prev_dirpos=0;
302   int mode=0;
303   uint32 size=0,len;
304   uint32 mdate=0, adate=0, cdate=0;
305   char *nameptr;
306   BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
307                     strequal(Connections[cnum].dirpath,".") ||
308                     strequal(Connections[cnum].dirpath,"/"));
309   BOOL was_8_3;
310   int nt_extmode; /* Used for NT connections instead of mode */
311   BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
312
313   *fname = 0;
314   *out_of_space = False;
315
316   if (!Connections[cnum].dirptr)
317     return(False);
318
319   p = strrchr(path_mask,'/');
320   if(p != NULL)
321     {
322       if(p[1] == '\0')
323         strcpy(mask,"*.*");
324       else
325         pstrcpy(mask, p+1);
326     }
327   else
328     pstrcpy(mask, path_mask);
329
330   while (!found)
331     {
332       /* Needed if we run out of space */
333       prev_dirpos = TellDir(Connections[cnum].dirptr);
334       dname = ReadDirName(Connections[cnum].dirptr);
335
336       reskey = TellDir(Connections[cnum].dirptr);
337
338       DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
339                Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
340       
341       if (!dname) 
342         return(False);
343
344       matched = False;
345
346       pstrcpy(fname,dname);      
347
348       if(mask_match(fname, mask, case_sensitive, True))
349         {
350           BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
351           if (dont_descend && !isdots)
352             continue;
353           
354           if (isrootdir && isdots)
355             continue;
356
357           pstrcpy(pathreal,Connections[cnum].dirpath);
358           if(needslash)
359             strcat(pathreal,"/");
360           strcat(pathreal,dname);
361           if (sys_stat(pathreal,&sbuf) != 0) 
362             {
363               DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
364               continue;
365             }
366
367           mode = dos_mode(cnum,pathreal,&sbuf);
368
369           if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) {
370             DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
371             continue;
372           }
373
374           size = sbuf.st_size;
375           mdate = sbuf.st_mtime;
376           adate = sbuf.st_atime;
377           cdate = get_create_time(&sbuf);
378           if(mode & aDIR)
379             size = 0;
380
381           DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
382           
383           found = True;
384         }
385     }
386
387   name_map_mangle(fname,False,SNUM(cnum));
388
389   p = pdata;
390   nameptr = p;
391
392   nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
393
394   switch (info_level)
395     {
396     case 1:
397       if(requires_resume_key) {
398         SIVAL(p,0,reskey);
399         p += 4;
400       }
401       put_dos_date2(p,l1_fdateCreation,cdate);
402       put_dos_date2(p,l1_fdateLastAccess,adate);
403       put_dos_date2(p,l1_fdateLastWrite,mdate);
404       SIVAL(p,l1_cbFile,size);
405       SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
406       SSVAL(p,l1_attrFile,mode);
407       SCVAL(p,l1_cchName,strlen(fname));
408       strcpy(p + l1_achName, fname);
409       nameptr = p + l1_achName;
410       p += l1_achName + strlen(fname) + 1;
411       break;
412
413     case 2:
414       /* info_level 2 */
415       if(requires_resume_key) {
416         SIVAL(p,0,reskey);
417         p += 4;
418       }
419       put_dos_date2(p,l2_fdateCreation,cdate);
420       put_dos_date2(p,l2_fdateLastAccess,adate);
421       put_dos_date2(p,l2_fdateLastWrite,mdate);
422       SIVAL(p,l2_cbFile,size);
423       SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
424       SSVAL(p,l2_attrFile,mode);
425       SIVAL(p,l2_cbList,0); /* No extended attributes */
426       SCVAL(p,l2_cchName,strlen(fname));
427       strcpy(p + l2_achName, fname);
428       nameptr = p + l2_achName;
429       p += l2_achName + strlen(fname) + 1;
430       break;
431
432     case 3:
433       SIVAL(p,0,reskey);
434       put_dos_date2(p,4,cdate);
435       put_dos_date2(p,8,adate);
436       put_dos_date2(p,12,mdate);
437       SIVAL(p,16,size);
438       SIVAL(p,20,ROUNDUP(size,1024));
439       SSVAL(p,24,mode);
440       SIVAL(p,26,4);
441       CVAL(p,30) = strlen(fname);
442       strcpy(p+31, fname);
443       nameptr = p+31;
444       p += 31 + strlen(fname) + 1;
445       break;
446
447     case 4:
448       if(requires_resume_key) {
449         SIVAL(p,0,reskey);
450         p += 4;
451       }
452       SIVAL(p,0,33+strlen(fname)+1);
453       put_dos_date2(p,4,cdate);
454       put_dos_date2(p,8,adate);
455       put_dos_date2(p,12,mdate);
456       SIVAL(p,16,size);
457       SIVAL(p,20,ROUNDUP(size,1024));
458       SSVAL(p,24,mode);
459       CVAL(p,32) = strlen(fname);
460       strcpy(p + 33, fname);
461       nameptr = p+33;
462       p += 33 + strlen(fname) + 1;
463       break;
464
465     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
466       was_8_3 = is_8_3(fname, True);
467       len = 94+strlen(fname);
468       len = (len + 3) & ~3;
469       SIVAL(p,0,len); p += 4;
470       SIVAL(p,0,reskey); p += 4;
471       put_long_date(p,cdate); p += 8;
472       put_long_date(p,adate); p += 8;
473       put_long_date(p,mdate); p += 8;
474       put_long_date(p,mdate); p += 8;
475       SIVAL(p,0,size); p += 8;
476       SIVAL(p,0,size); p += 8;
477       SIVAL(p,0,nt_extmode); p += 4;
478       SIVAL(p,0,strlen(fname)); p += 4;
479       SIVAL(p,0,0); p += 4;
480       if (!was_8_3) {
481         strcpy(p+2,fname);
482         if (!name_map_mangle(p+2,True,SNUM(cnum)))
483           (p+2)[12] = 0;
484       } else
485         *(p+2) = 0;
486       strupper(p+2);
487       SSVAL(p,0,strlen(p+2));
488       p += 2 + 24;
489       /* nameptr = p;  */
490       strcpy(p,fname); p += strlen(p);
491       p = pdata + len;
492       break;
493
494     case SMB_FIND_FILE_DIRECTORY_INFO:
495       len = 64+strlen(fname);
496       len = (len + 3) & ~3;
497       SIVAL(p,0,len); p += 4;
498       SIVAL(p,0,reskey); p += 4;
499       put_long_date(p,cdate); p += 8;
500       put_long_date(p,adate); p += 8;
501       put_long_date(p,mdate); p += 8;
502       put_long_date(p,mdate); p += 8;
503       SIVAL(p,0,size); p += 8;
504       SIVAL(p,0,size); p += 8;
505       SIVAL(p,0,nt_extmode); p += 4;
506       SIVAL(p,0,strlen(fname)); p += 4;
507       strcpy(p,fname);
508       p = pdata + len;
509       break;
510       
511       
512     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
513       len = 68+strlen(fname);
514       len = (len + 3) & ~3;
515       SIVAL(p,0,len); p += 4;
516       SIVAL(p,0,reskey); p += 4;
517       put_long_date(p,cdate); p += 8;
518       put_long_date(p,adate); p += 8;
519       put_long_date(p,mdate); p += 8;
520       put_long_date(p,mdate); p += 8;
521       SIVAL(p,0,size); p += 8;
522       SIVAL(p,0,size); p += 8;
523       SIVAL(p,0,nt_extmode); p += 4;
524       SIVAL(p,0,strlen(fname)); p += 4;
525       SIVAL(p,0,0); p += 4;
526       strcpy(p,fname);
527       p = pdata + len;
528       break;
529
530     case SMB_FIND_FILE_NAMES_INFO:
531       len = 12+strlen(fname);
532       len = (len + 3) & ~3;
533       SIVAL(p,0,len); p += 4;
534       SIVAL(p,0,reskey); p += 4;
535       SIVAL(p,0,strlen(fname)); p += 4;
536       strcpy(p,fname);
537       p = pdata + len;
538       break;
539
540     default:      
541       return(False);
542     }
543
544
545   if (PTR_DIFF(p,pdata) > space_remaining) {
546     /* Move the dirptr back to prev_dirpos */
547     SeekDir(Connections[cnum].dirptr, prev_dirpos);
548     *out_of_space = True;
549     DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
550     return False; /* Not finished - just out of space */
551   }
552
553   /* Setup the last_filename pointer, as an offset from base_data */
554   *last_name_off = PTR_DIFF(nameptr,base_data);
555   /* Advance the data pointer to the next slot */
556   *ppdata = p;
557   return(found);
558 }
559   
560 /****************************************************************************
561   reply to a TRANS2_FINDFIRST
562 ****************************************************************************/
563 static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum, 
564                          char **pparams, char **ppdata)
565 {
566   /* We must be careful here that we don't return more than the
567      allowed number of data bytes. If this means returning fewer than
568      maxentries then so be it. We assume that the redirector has
569      enough room for the fixed number of parameter bytes it has
570      requested. */
571   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
572   char *params = *pparams;
573   char *pdata = *ppdata;
574   int dirtype = SVAL(params,0);
575   int maxentries = SVAL(params,2);
576   BOOL close_after_first = BITSETW(params+4,0);
577   BOOL close_if_end = BITSETW(params+4,1);
578   BOOL requires_resume_key = BITSETW(params+4,2);
579   int info_level = SVAL(params,6);
580   pstring directory;
581   pstring mask;
582   char *p, *wcard;
583   int last_name_off=0;
584   int dptr_num = -1;
585   int numentries = 0;
586   int i;
587   BOOL finished = False;
588   BOOL dont_descend = False;
589   BOOL out_of_space = False;
590   int space_remaining;
591   BOOL bad_path = False;
592
593   *directory = *mask = 0;
594
595   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",
596            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
597            info_level, max_data_bytes));
598   
599   switch (info_level) 
600     {
601     case 1:
602     case 2:
603     case 3:
604     case 4:
605     case SMB_FIND_FILE_DIRECTORY_INFO:
606     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
607     case SMB_FIND_FILE_NAMES_INFO:
608     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
609       break;
610     default:
611       return(ERROR(ERRDOS,ERRunknownlevel));
612     }
613
614   pstrcpy(directory, params + 12); /* Complete directory path with 
615                                      wildcard mask appended */
616
617   DEBUG(5,("path=%s\n",directory));
618
619   unix_convert(directory,cnum,0,&bad_path);
620   if(!check_name(directory,cnum)) {
621     if((errno == ENOENT) && bad_path)
622     {
623       unix_ERR_class = ERRDOS;
624       unix_ERR_code = ERRbadpath;
625     }
626
627 #if 0
628     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
629     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
630        (get_remote_arch() == RA_WINNT))
631     {
632       unix_ERR_class = ERRDOS;
633       unix_ERR_code = ERRbaddirectory;
634     }
635 #endif 
636
637     return(ERROR(ERRDOS,ERRbadpath));
638   }
639
640   p = strrchr(directory,'/');
641   if(p == NULL) {
642     strcpy(mask,directory);
643     strcpy(directory,"./");
644   } else {
645     strcpy(mask,p+1);
646     *p = 0;
647   }
648
649   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
650
651   pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
652   if(!*ppdata)
653     return(ERROR(ERRDOS,ERRnomem));
654   bzero(pdata,max_data_bytes);
655
656   /* Realloc the params space */
657   params = *pparams = Realloc(*pparams, 10);
658   if(params == NULL)
659     return(ERROR(ERRDOS,ERRnomem));
660
661   dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
662   if (dptr_num < 0)
663     return(ERROR(ERRDOS,ERRbadfile));
664
665   /* convert the formatted masks */
666   {
667     p = mask;
668     while (*p) {
669       if (*p == '<') *p = '*';
670       if (*p == '>') *p = '?';
671       if (*p == '"') *p = '.';
672       p++;
673     }
674   }
675   
676   /* a special case for 16 bit apps */
677   if (strequal(mask,"????????.???")) strcpy(mask,"*");
678
679   /* handle broken clients that send us old 8.3 format */
680   string_sub(mask,"????????","*");
681   string_sub(mask,".???",".*");
682
683   /* Save the wildcard match and attribs we are using on this directory - 
684      needed as lanman2 assumes these are being saved between calls */
685
686   if(!(wcard = strdup(mask))) {
687     dptr_close(dptr_num);
688     return(ERROR(ERRDOS,ERRnomem));
689   }
690
691   dptr_set_wcard(dptr_num, wcard);
692   dptr_set_attr(dptr_num, dirtype);
693
694   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
695
696   /* We don't need to check for VOL here as this is returned by 
697      a different TRANS2 call. */
698   
699   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
700            Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
701   if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive))
702     dont_descend = True;
703     
704   p = pdata;
705   space_remaining = max_data_bytes;
706   out_of_space = False;
707
708   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
709     {
710
711       /* this is a heuristic to avoid seeking the dirptr except when 
712          absolutely necessary. It allows for a filename of about 40 chars */
713       if (space_remaining < DIRLEN_GUESS && numentries > 0)
714         {
715           out_of_space = True;
716           finished = False;
717         }
718       else
719         {
720           finished = 
721             !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
722                                    requires_resume_key,dont_descend,
723                                    &p,pdata,space_remaining, &out_of_space,
724                                    &last_name_off);
725         }
726
727       if (finished && out_of_space)
728         finished = False;
729
730       if (!finished && !out_of_space)
731         numentries++;
732       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
733     }
734   
735   /* Check if we can close the dirptr */
736   if(close_after_first || (finished && close_if_end))
737     {
738       dptr_close(dptr_num);
739       DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
740       dptr_num = -1;
741     }
742
743   /* 
744    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
745    * from observation of NT.
746    */
747
748   if(numentries == 0)
749     return(ERROR(ERRDOS,ERRbadfile));
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,get_create_time(&sbuf));
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,get_create_time(&sbuf));
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,get_create_time(&sbuf));
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       {
1166         time_t create_time = get_create_time(&sbuf);
1167         DEBUG(5,("create: %s ", ctime(&create_time)));
1168       }
1169       DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1170       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1171       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1172       DEBUG(5,("mode: %x\n", mode));
1173
1174       break;
1175
1176     case SMB_QUERY_FILE_STANDARD_INFO:
1177       data_size = 22;
1178       SIVAL(pdata,0,size);
1179       SIVAL(pdata,8,size);
1180       SIVAL(pdata,16,sbuf.st_nlink);
1181       CVAL(pdata,20) = 0;
1182       CVAL(pdata,21) = (mode&aDIR)?1:0;
1183       break;
1184
1185     case SMB_QUERY_FILE_EA_INFO:
1186       data_size = 4;
1187       break;
1188
1189     /* Get the 8.3 name - used if NT SMB was negotiated. */
1190     case SMB_QUERY_FILE_ALT_NAME_INFO:
1191       {
1192         pstring short_name;
1193         pstrcpy(short_name,fname);
1194         /* Mangle if not already 8.3 */
1195         if(!is_8_3(short_name, True))
1196         {
1197           if(!name_map_mangle(short_name,True,SNUM(cnum)))
1198             *short_name = '\0';
1199         }
1200         strncpy(pdata + 4,short_name,12);
1201         (pdata + 4)[12] = 0;
1202         strupper(pdata + 4);
1203         l = strlen(pdata + 4);
1204         data_size = 4 + l;
1205         SIVAL(pdata,0,l);
1206       }
1207       break;
1208
1209     case SMB_QUERY_FILE_NAME_INFO:
1210       data_size = 4 + l;
1211       SIVAL(pdata,0,l);
1212       pstrcpy(pdata+4,fname);
1213       break;
1214
1215     case SMB_QUERY_FILE_ALLOCATION_INFO:
1216     case SMB_QUERY_FILE_END_OF_FILEINFO:
1217       data_size = 8;
1218       SIVAL(pdata,0,size);
1219       break;
1220
1221     case SMB_QUERY_FILE_ALL_INFO:
1222       put_long_date(pdata,get_create_time(&sbuf));
1223       put_long_date(pdata+8,sbuf.st_atime); /* access time */
1224       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1225       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1226       SIVAL(pdata,32,mode);
1227       pdata += 40;
1228       SIVAL(pdata,0,size);
1229       SIVAL(pdata,8,size);
1230       SIVAL(pdata,16,sbuf.st_nlink);
1231       CVAL(pdata,20) = 0;
1232       CVAL(pdata,21) = (mode&aDIR)?1:0;
1233       pdata += 24;
1234       pdata += 8; /* index number */
1235       pdata += 4; /* EA info */
1236       if (mode & aRONLY)
1237         SIVAL(pdata,0,0xA9);
1238       else
1239         SIVAL(pdata,0,0xd01BF);
1240       pdata += 4;
1241       SIVAL(pdata,0,pos); /* current offset */
1242       pdata += 8;
1243       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1244       pdata += 4;
1245       pdata += 4; /* alignment */
1246       SIVAL(pdata,0,l);
1247       pstrcpy(pdata+4,fname);
1248       pdata += 4 + l;
1249       data_size = PTR_DIFF(pdata,(*ppdata));
1250       break;
1251
1252     case SMB_QUERY_FILE_STREAM_INFO:
1253       data_size = 24 + l;
1254       SIVAL(pdata,0,pos);
1255       SIVAL(pdata,4,size);
1256       SIVAL(pdata,12,size);
1257       SIVAL(pdata,20,l);        
1258       pstrcpy(pdata+24,fname);
1259       break;
1260     default:
1261       return(ERROR(ERRDOS,ERRunknownlevel));
1262     }
1263
1264   send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1265
1266   return(-1);
1267 }
1268
1269 /****************************************************************************
1270   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1271 ****************************************************************************/
1272 static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, 
1273                                       int bufsize, int cnum, char **pparams, 
1274                                       char **ppdata, int total_data)
1275 {
1276   char *params = *pparams;
1277   char *pdata = *ppdata;
1278   uint16 tran_call = SVAL(inbuf, smb_setup0);
1279   uint16 info_level;
1280   int mode=0;
1281   int size=0;
1282   struct utimbuf tvs;
1283   struct stat st;
1284   pstring fname1;
1285   char *fname;
1286   int fd = -1;
1287   BOOL bad_path = False;
1288
1289   if (!CAN_WRITE(cnum))
1290     return(ERROR(ERRSRV,ERRaccess));
1291
1292   if (tran_call == TRANSACT2_SETFILEINFO) {
1293     int16 fnum = SVALS(params,0);
1294     info_level = SVAL(params,2);    
1295
1296     CHECK_FNUM(fnum,cnum);
1297     CHECK_ERROR(fnum);
1298
1299     fname = Files[fnum].name;
1300     fd = Files[fnum].fd_ptr->fd;
1301
1302     if(fstat(fd,&st)!=0) {
1303       DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1304       return(ERROR(ERRDOS,ERRbadpath));
1305     }
1306   } else {
1307     /* set path info */
1308     info_level = SVAL(params,0);    
1309     fname = fname1;
1310     pstrcpy(fname,&params[6]);
1311     unix_convert(fname,cnum,0,&bad_path);
1312     if(!check_name(fname, cnum))
1313     {
1314       if((errno == ENOENT) && bad_path)
1315       {
1316         unix_ERR_class = ERRDOS;
1317         unix_ERR_code = ERRbadpath;
1318       }
1319       return(UNIXERROR(ERRDOS,ERRbadpath));
1320     }
1321  
1322     if(sys_stat(fname,&st)!=0) {
1323       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1324       if((errno == ENOENT) && bad_path)
1325       {
1326         unix_ERR_class = ERRDOS;
1327         unix_ERR_code = ERRbadpath;
1328       }
1329       return(UNIXERROR(ERRDOS,ERRbadpath));
1330     }    
1331   }
1332
1333   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1334            tran_call,fname,info_level,total_data));
1335
1336   /* Realloc the parameter and data sizes */
1337   params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1338   if(params == NULL)
1339     return(ERROR(ERRDOS,ERRnomem));
1340
1341   size = st.st_size;
1342   tvs.modtime = st.st_mtime;
1343   tvs.actime = st.st_atime;
1344   mode = dos_mode(cnum,fname,&st);
1345
1346   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1347     /* uggh, EAs for OS2 */
1348     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1349     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1350   }
1351
1352   switch (info_level)
1353   {
1354     case SMB_INFO_STANDARD:
1355     case SMB_INFO_QUERY_EA_SIZE:
1356     {
1357       /* access time */
1358       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1359
1360       /* write time */
1361       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1362
1363       mode = SVAL(pdata,l1_attrFile);
1364       size = IVAL(pdata,l1_cbFile);
1365       break;
1366     }
1367
1368     /* XXXX um, i don't think this is right.
1369        it's also not in the cifs6.txt spec.
1370      */
1371     case SMB_INFO_QUERY_EAS_FROM_LIST:
1372       tvs.actime = make_unix_date2(pdata+8);
1373       tvs.modtime = make_unix_date2(pdata+12);
1374       size = IVAL(pdata,16);
1375       mode = IVAL(pdata,24);
1376       break;
1377
1378     /* XXXX nor this.  not in cifs6.txt, either. */
1379     case SMB_INFO_QUERY_ALL_EAS:
1380       tvs.actime = make_unix_date2(pdata+8);
1381       tvs.modtime = make_unix_date2(pdata+12);
1382       size = IVAL(pdata,16);
1383       mode = IVAL(pdata,24);
1384       break;
1385
1386     case SMB_SET_FILE_BASIC_INFO:
1387     {
1388       /* Ignore create time at offset pdata. */
1389
1390       /* access time */
1391       tvs.actime = interpret_long_date(pdata+8);
1392
1393       /* write time + changed time, combined. */
1394       tvs.modtime=MAX(interpret_long_date(pdata+16),
1395                       interpret_long_date(pdata+24));
1396
1397 #if 0 /* Needs more testing... */
1398       /* Test from Luke to prevent Win95 from
1399          setting incorrect values here.
1400        */
1401       if (tvs.actime < tvs.modtime)
1402         return(ERROR(ERRDOS,ERRnoaccess));
1403 #endif /* Needs more testing... */
1404
1405       /* attributes */
1406       mode = IVAL(pdata,32);
1407       break;
1408     }
1409
1410     case SMB_SET_FILE_END_OF_FILE_INFO:
1411     {
1412       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1413          return(ERROR(ERRDOS,ERRunknownlevel));
1414       size = IVAL(pdata,0);
1415       break;
1416     }
1417
1418     case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1419     case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1420     default:
1421     {
1422       return(ERROR(ERRDOS,ERRunknownlevel));
1423     }
1424   }
1425
1426   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1427   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1428   DEBUG(6,("size: %x "   , size));
1429   DEBUG(6,("mode: %x\n"  , mode));
1430
1431   /* get some defaults (no modifications) if any info is zero. */
1432   if (!tvs.actime) tvs.actime = st.st_atime;
1433   if (!tvs.modtime) tvs.modtime = st.st_mtime;
1434   if (!size) size = st.st_size;
1435
1436   /* Try and set the times, size and mode of this file -
1437      if they are different from the current values
1438    */
1439   if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1440   {
1441     if(file_utime(cnum, fname, &tvs)!=0)
1442     {
1443       return(ERROR(ERRDOS,ERRnoaccess));
1444     }
1445   }
1446
1447   /* check the mode isn't different, before changing it */
1448   if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
1449   {
1450     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1451     return(ERROR(ERRDOS,ERRnoaccess));
1452   }
1453
1454   if(size != st.st_size)
1455   {
1456     if (fd == -1)
1457     {
1458       fd = sys_open(fname,O_RDWR,0);
1459       if (fd == -1)
1460       {
1461         return(ERROR(ERRDOS,ERRbadpath));
1462       }
1463       set_filelen(fd, size);
1464       close(fd);
1465     }
1466     else
1467     {
1468       set_filelen(fd, size);
1469     }
1470   }
1471
1472   SSVAL(params,0,0);
1473
1474   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1475   
1476   return(-1);
1477 }
1478
1479 /****************************************************************************
1480   reply to a TRANS2_MKDIR (make directory with extended attributes).
1481 ****************************************************************************/
1482 static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
1483                         int cnum, char **pparams, char **ppdata)
1484 {
1485   char *params = *pparams;
1486   pstring directory;
1487   int ret = -1;
1488   BOOL bad_path = False;
1489
1490   if (!CAN_WRITE(cnum))
1491     return(ERROR(ERRSRV,ERRaccess));
1492
1493   pstrcpy(directory, &params[4]);
1494
1495   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1496
1497   unix_convert(directory,cnum,0,&bad_path);
1498   if (check_name(directory,cnum))
1499     ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
1500   
1501   if(ret < 0)
1502     {
1503       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1504       if((errno == ENOENT) && bad_path)
1505       {
1506         unix_ERR_class = ERRDOS;
1507         unix_ERR_code = ERRbadpath;
1508       }
1509       return(UNIXERROR(ERRDOS,ERRnoaccess));
1510     }
1511
1512   /* Realloc the parameter and data sizes */
1513   params = *pparams = Realloc(*pparams,2);
1514   if(params == NULL)
1515     return(ERROR(ERRDOS,ERRnomem));
1516
1517   SSVAL(params,0,0);
1518
1519   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1520   
1521   return(-1);
1522 }
1523
1524 /****************************************************************************
1525   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1526   We don't actually do this - we just send a null response.
1527 ****************************************************************************/
1528 static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
1529                         int cnum, char **pparams, char **ppdata)
1530 {
1531   static uint16 fnf_handle = 257;
1532   char *params = *pparams;
1533   uint16 info_level = SVAL(params,4);
1534
1535   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1536
1537   switch (info_level) 
1538     {
1539     case 1:
1540     case 2:
1541       break;
1542     default:
1543       return(ERROR(ERRDOS,ERRunknownlevel));
1544     }
1545
1546   /* Realloc the parameter and data sizes */
1547   params = *pparams = Realloc(*pparams,6);
1548   if(params == NULL)
1549     return(ERROR(ERRDOS,ERRnomem));
1550
1551   SSVAL(params,0,fnf_handle);
1552   SSVAL(params,2,0); /* No changes */
1553   SSVAL(params,4,0); /* No EA errors */
1554
1555   fnf_handle++;
1556
1557   if(fnf_handle == 0)
1558     fnf_handle = 257;
1559
1560   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1561   
1562   return(-1);
1563 }
1564
1565 /****************************************************************************
1566   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
1567   changes). Currently this does nothing.
1568 ****************************************************************************/
1569 static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
1570                         int cnum, char **pparams, char **ppdata)
1571 {
1572   char *params = *pparams;
1573
1574   DEBUG(3,("call_trans2findnotifynext\n"));
1575
1576   /* Realloc the parameter and data sizes */
1577   params = *pparams = Realloc(*pparams,4);
1578   if(params == NULL)
1579     return(ERROR(ERRDOS,ERRnomem));
1580
1581   SSVAL(params,0,0); /* No changes */
1582   SSVAL(params,2,0); /* No EA errors */
1583
1584   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1585   
1586   return(-1);
1587 }
1588
1589 /****************************************************************************
1590   reply to a SMBfindclose (stop trans2 directory search)
1591 ****************************************************************************/
1592 int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
1593 {
1594   int cnum;
1595   int outsize = 0;
1596   int16 dptr_num=SVALS(inbuf,smb_vwv0);
1597
1598   cnum = SVAL(inbuf,smb_tid);
1599
1600   DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1601
1602   dptr_close(dptr_num);
1603
1604   outsize = set_message(outbuf,0,0,True);
1605
1606   DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1607
1608   return(outsize);
1609 }
1610
1611 /****************************************************************************
1612   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1613 ****************************************************************************/
1614 int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
1615 {
1616   int cnum;
1617   int outsize = 0;
1618   int dptr_num= -1;
1619
1620   cnum = SVAL(inbuf,smb_tid);
1621   dptr_num = SVAL(inbuf,smb_vwv0);
1622
1623   DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
1624
1625   /* We never give out valid handles for a 
1626      findnotifyfirst - so any dptr_num is ok here. 
1627      Just ignore it. */
1628
1629   outsize = set_message(outbuf,0,0,True);
1630
1631   DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
1632
1633   return(outsize);
1634 }
1635
1636
1637 /****************************************************************************
1638   reply to a SMBtranss2 - just ignore it!
1639 ****************************************************************************/
1640 int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize)
1641 {
1642   DEBUG(4,("Ignoring transs2 of length %d\n",length));
1643   return(-1);
1644 }
1645
1646 /****************************************************************************
1647   reply to a SMBtrans2
1648 ****************************************************************************/
1649 int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
1650 {
1651   int outsize = 0;
1652   int cnum = SVAL(inbuf,smb_tid);
1653   unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1654   unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1655 #if 0
1656   unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1657   unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1658   unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1659   BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1660   BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1661   int32 timeout = IVALS(inbuf,smb_timeout);
1662 #endif
1663   unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1664   unsigned int tran_call = SVAL(inbuf, smb_setup0);
1665   char *params = NULL, *data = NULL;
1666   int num_params, num_params_sofar, num_data, num_data_sofar;
1667
1668   outsize = set_message(outbuf,0,0,True);
1669
1670   /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1671      is so as a sanity check */
1672   if(suwcnt != 1 )
1673     {
1674       DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1675       return(ERROR(ERRSRV,ERRerror));
1676     }
1677     
1678   /* Allocate the space for the maximum needed parameters and data */
1679   if (total_params > 0)
1680     params = (char *)malloc(total_params);
1681   if (total_data > 0)
1682     data = (char *)malloc(total_data);
1683   
1684   if ((total_params && !params)  || (total_data && !data))
1685     {
1686       DEBUG(2,("Out of memory in reply_trans2\n"));
1687       return(ERROR(ERRDOS,ERRnomem));
1688     }
1689
1690   /* Copy the param and data bytes sent with this request into
1691      the params buffer */
1692   num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1693   num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1694
1695   if (num_params > total_params || num_data > total_data)
1696           exit_server("invalid params in reply_trans2");
1697
1698   memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1699   memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1700
1701   if(num_data_sofar < total_data || num_params_sofar < total_params)
1702     {
1703     /* We need to send an interim response then receive the rest
1704        of the parameter/data bytes */
1705       outsize = set_message(outbuf,0,0,True);
1706       send_smb(Client,outbuf);
1707
1708       while( num_data_sofar < total_data || num_params_sofar < total_params)
1709         {
1710           BOOL ret;
1711
1712           ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1713                              SMB_SECONDARY_WAIT);
1714
1715           if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret)
1716             {
1717               outsize = set_message(outbuf,0,0,True);
1718               if(ret)
1719                 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1720               else
1721                 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1722                          (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1723               free(params);
1724               free(data);
1725               return(ERROR(ERRSRV,ERRerror));
1726             }
1727       
1728           /* Revise total_params and total_data in case they have changed downwards */
1729           total_params = SVAL(inbuf, smb_tpscnt);
1730           total_data = SVAL(inbuf, smb_tdscnt);
1731           num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1732           num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1733           if (num_params_sofar > total_params || num_data_sofar > total_data)
1734                   exit_server("data overflow in trans2");
1735
1736           memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
1737                  smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1738           memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1739                  smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1740         }
1741     }
1742
1743   if (Protocol >= PROTOCOL_NT1) {
1744     uint16 flg2 = SVAL(outbuf,smb_flg2);
1745     SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1746   }
1747
1748   /* Now we must call the relevant TRANS2 function */
1749   switch(tran_call) 
1750     {
1751     case TRANSACT2_OPEN:
1752       outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, &params, &data);
1753       break;
1754     case TRANSACT2_FINDFIRST:
1755       outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, &params, &data);
1756       break;
1757     case TRANSACT2_FINDNEXT:
1758       outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1759       break;
1760     case TRANSACT2_QFSINFO:
1761       outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1762       break;
1763     case TRANSACT2_SETFSINFO:
1764       outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1765       break;
1766     case TRANSACT2_QPATHINFO:
1767     case TRANSACT2_QFILEINFO:
1768       outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1769       break;
1770     case TRANSACT2_SETPATHINFO:
1771     case TRANSACT2_SETFILEINFO:
1772       outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, &params, &data, total_data);
1773       break;
1774     case TRANSACT2_FINDNOTIFYFIRST:
1775       outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1776       break;
1777     case TRANSACT2_FINDNOTIFYNEXT:
1778       outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1779       break;
1780     case TRANSACT2_MKDIR:
1781       outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, &params, &data);
1782       break;
1783     default:
1784       /* Error in request */
1785       DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
1786       if(params)
1787         free(params);
1788       if(data)
1789         free(data);
1790       return (ERROR(ERRSRV,ERRerror));
1791     }
1792
1793   /* As we do not know how many data packets will need to be
1794      returned here the various call_trans2xxxx calls
1795      must send their own. Thus a call_trans2xxx routine only
1796      returns a value other than -1 when it wants to send
1797      an error packet. 
1798   */
1799
1800   if(params)
1801     free(params);
1802   if(data)
1803     free(data);
1804   return outsize; /* If a correct response was needed the call_trans2xxx 
1805                      calls have already sent it. If outsize != -1 then it is
1806                      returning an error packet. */
1807 }