Jean-Francois Micouleau's rewritten DFS patch, originally written by
[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 BOOL case_sensitive;
30 extern int Client;
31 extern int smb_read_error;
32 extern fstring local_machine;
33 extern int global_oplock_break;
34 extern dfs_internal dfs_struct;
35
36 /****************************************************************************
37   Send the required number of replies back.
38   We assume all fields other than the data fields are
39   set correctly for the type of call.
40   HACK ! Always assumes smb_setup field is zero.
41 ****************************************************************************/
42 static int send_trans2_replies(char *outbuf, int bufsize, char *params, 
43                                int paramsize, char *pdata, int datasize)
44 {
45   /* As we are using a protocol > LANMAN1 then the max_send
46      variable must have been set in the sessetupX call.
47      This takes precedence over the max_xmit field in the
48      global struct. These different max_xmit variables should
49      be merged as this is now too confusing */
50
51   extern int max_send;
52   int data_to_send = datasize;
53   int params_to_send = paramsize;
54   int useable_space;
55   char *pp = params;
56   char *pd = pdata;
57   int params_sent_thistime, data_sent_thistime, total_sent_thistime;
58   int alignment_offset = 3;
59   int data_alignment_offset = 0;
60
61   /* Initially set the wcnt area to be 10 - this is true for all
62      trans2 replies */
63   set_message(outbuf,10,0,True);
64
65   /* If there genuinely are no parameters or data to send just send
66      the empty packet */
67   if(params_to_send == 0 && data_to_send == 0)
68   {
69     send_smb(Client,outbuf);
70     return 0;
71   }
72
73   /* When sending params and data ensure that both are nicely aligned */
74   /* Only do this alignment when there is also data to send - else
75      can cause NT redirector problems. */
76   if (((params_to_send % 4) != 0) && (data_to_send != 0))
77     data_alignment_offset = 4 - (params_to_send % 4);
78
79   /* Space is bufsize minus Netbios over TCP header minus SMB header */
80   /* The alignment_offset is to align the param bytes on an even byte
81      boundary. NT 4.0 Beta needs this to work correctly. */
82   useable_space = bufsize - ((smb_buf(outbuf)+
83                     alignment_offset+data_alignment_offset) - 
84                     outbuf);
85
86   /* useable_space can never be more than max_send minus the
87      alignment offset. */
88   useable_space = MIN(useable_space, 
89                       max_send - (alignment_offset+data_alignment_offset));
90
91
92   while (params_to_send || data_to_send)
93   {
94     /* Calculate whether we will totally or partially fill this packet */
95     total_sent_thistime = params_to_send + data_to_send + 
96                             alignment_offset + data_alignment_offset;
97     /* We can never send more than useable_space */
98     total_sent_thistime = MIN(total_sent_thistime, useable_space);
99
100     set_message(outbuf, 10, total_sent_thistime, True);
101
102     /* Set total params and data to be sent */
103     SSVAL(outbuf,smb_tprcnt,paramsize);
104     SSVAL(outbuf,smb_tdrcnt,datasize);
105
106     /* Calculate how many parameters and data we can fit into
107        this packet. Parameters get precedence */
108
109     params_sent_thistime = MIN(params_to_send,useable_space);
110     data_sent_thistime = useable_space - params_sent_thistime;
111     data_sent_thistime = MIN(data_sent_thistime,data_to_send);
112
113     SSVAL(outbuf,smb_prcnt, params_sent_thistime);
114     if(params_sent_thistime == 0)
115     {
116       /*SSVAL(outbuf,smb_proff,0);*/
117       SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
118       SSVAL(outbuf,smb_prdisp,0);
119     }
120     else
121     {
122       /* smb_proff is the offset from the start of the SMB header to the
123          parameter bytes, however the first 4 bytes of outbuf are
124          the Netbios over TCP header. Thus use smb_base() to subtract
125          them from the calculation */
126       SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
127       /* Absolute displacement of param bytes sent in this packet */
128       SSVAL(outbuf,smb_prdisp,pp - params);
129     }
130
131     SSVAL(outbuf,smb_drcnt, data_sent_thistime);
132     if(data_sent_thistime == 0)
133     {
134       SSVAL(outbuf,smb_droff,0);
135       SSVAL(outbuf,smb_drdisp, 0);
136     }
137     else
138     {
139       /* The offset of the data bytes is the offset of the
140          parameter bytes plus the number of parameters being sent this time */
141       SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
142             smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
143       SSVAL(outbuf,smb_drdisp, pd - pdata);
144     }
145
146     /* Copy the param bytes into the packet */
147     if(params_sent_thistime)
148       memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
149     /* Copy in the data bytes */
150     if(data_sent_thistime)
151       memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
152              data_alignment_offset,pd,data_sent_thistime);
153
154     DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
155           params_sent_thistime, data_sent_thistime, useable_space));
156     DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
157           params_to_send, data_to_send, paramsize, datasize));
158
159     /* Send the packet */
160     send_smb(Client,outbuf);
161
162     pp += params_sent_thistime;
163     pd += data_sent_thistime;
164
165     params_to_send -= params_sent_thistime;
166     data_to_send -= data_sent_thistime;
167
168     /* Sanity check */
169     if(params_to_send < 0 || data_to_send < 0)
170     {
171       DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
172             params_to_send, data_to_send));
173       return -1;
174     }
175   }
176
177   return 0;
178 }
179
180
181 /****************************************************************************
182   reply to a TRANSACT2_OPEN
183 ****************************************************************************/
184 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, 
185                            int bufsize,  
186                            char **pparams, char **ppdata)
187 {
188   char *params = *pparams;
189   int16 open_mode = SVAL(params, 2);
190   int16 open_attr = SVAL(params,6);
191   BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
192 #if 0
193   BOOL return_additional_info = BITSETW(params,0);
194   int16 open_sattr = SVAL(params, 4);
195   time_t open_time = make_unix_date3(params+8);
196 #endif
197   int16 open_ofun = SVAL(params,12);
198   int32 open_size = IVAL(params,14);
199   char *pname = &params[28];
200   int16 namelen = strlen(pname)+1;
201
202   pstring fname;
203   mode_t unixmode;
204   SMB_OFF_T size=0;
205   int fmode=0,mtime=0,rmode;
206   SMB_INO_T inode = 0;
207   SMB_STRUCT_STAT sbuf;
208   int smb_action = 0;
209   BOOL bad_path = False;
210   files_struct *fsp;
211
212   StrnCpy(fname,pname,namelen);
213
214   DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
215            fname,open_mode, open_attr, open_ofun, open_size));
216
217   /* XXXX we need to handle passed times, sattr and flags */
218
219   unix_convert(fname,conn,0,&bad_path,NULL);
220     
221   fsp = file_new();
222   if (!fsp)
223     return(ERROR(ERRSRV,ERRnofids));
224
225   if (!check_name(fname,conn))
226   {
227     if((errno == ENOENT) && bad_path)
228     {
229       unix_ERR_class = ERRDOS;
230       unix_ERR_code = ERRbadpath;
231     }
232     file_free(fsp);
233     return(UNIXERROR(ERRDOS,ERRnoaccess));
234   }
235
236   unixmode = unix_mode(conn,open_attr | aARCH);
237       
238   open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode,
239                    oplock_request, &rmode,&smb_action);
240       
241   if (!fsp->open)
242   {
243     if((errno == ENOENT) && bad_path)
244     {
245       unix_ERR_class = ERRDOS;
246       unix_ERR_code = ERRbadpath;
247     }
248     file_free(fsp);
249     return(UNIXERROR(ERRDOS,ERRnoaccess));
250   }
251
252   if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
253     close_file(fsp,False);
254     return(UNIXERROR(ERRDOS,ERRnoaccess));
255   }
256     
257   size = sbuf.st_size;
258   fmode = dos_mode(conn,fname,&sbuf);
259   mtime = sbuf.st_mtime;
260   inode = sbuf.st_ino;
261   if (fmode & aDIR) {
262     close_file(fsp,False);
263     return(ERROR(ERRDOS,ERRnoaccess));
264   }
265
266   /* Realloc the size of parameters and data we will return */
267   params = *pparams = Realloc(*pparams, 28);
268   if(params == NULL)
269     return(ERROR(ERRDOS,ERRnomem));
270
271   bzero(params,28);
272   SSVAL(params,0,fsp->fnum);
273   SSVAL(params,2,fmode);
274   put_dos_date2(params,4, mtime);
275   SIVAL(params,8, (uint32)size);
276   SSVAL(params,12,rmode);
277
278   if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
279     smb_action |= EXTENDED_OPLOCK_GRANTED;
280   }
281
282   SSVAL(params,18,smb_action);
283   /*
284    * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
285    */
286   SIVAL(params,20,inode);
287  
288   /* Send the required number of replies */
289   send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
290
291   return -1;
292 }
293
294 /****************************************************************************
295   get a level dependent lanman2 dir entry.
296 ****************************************************************************/
297 static int get_lanman2_dir_entry(connection_struct *conn,
298                                  char *path_mask,int dirtype,int info_level,
299                                  int requires_resume_key,
300                                  BOOL dont_descend,char **ppdata, 
301                                  char *base_data, int space_remaining, 
302                                  BOOL *out_of_space,
303                                  int *last_name_off)
304 {
305   char *dname;
306   BOOL found = False;
307   SMB_STRUCT_STAT sbuf;
308   pstring mask;
309   pstring pathreal;
310   pstring fname;
311   char *p, *pdata = *ppdata;
312   uint32 reskey=0;
313   int prev_dirpos=0;
314   int mode=0;
315   SMB_OFF_T size = 0;
316   uint32 len;
317   time_t mdate=0, adate=0, cdate=0;
318   char *nameptr;
319   BOOL isrootdir = (strequal(conn->dirpath,"./") ||
320                     strequal(conn->dirpath,".") ||
321                     strequal(conn->dirpath,"/"));
322   BOOL was_8_3;
323   int nt_extmode; /* Used for NT connections instead of mode */
324   BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
325
326   *fname = 0;
327   *out_of_space = False;
328
329   if (!conn->dirptr)
330     return(False);
331
332   p = strrchr(path_mask,'/');
333   if(p != NULL)
334   {
335     if(p[1] == '\0')
336       pstrcpy(mask,"*.*");
337     else
338       pstrcpy(mask, p+1);
339   }
340   else
341     pstrcpy(mask, path_mask);
342
343   while (!found)
344   {
345     /* Needed if we run out of space */
346     prev_dirpos = TellDir(conn->dirptr);
347     dname = ReadDirName(conn->dirptr);
348
349     /*
350      * Due to bugs in NT client redirectors we are not using
351      * resume keys any more - set them to zero.
352      * Check out the related comments in findfirst/findnext.
353      * JRA.
354      */
355
356     reskey = 0;
357
358     DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
359       (long)conn->dirptr,TellDir(conn->dirptr)));
360       
361     if (!dname) 
362       return(False);
363
364     pstrcpy(fname,dname);      
365
366     if(mask_match(fname, mask, case_sensitive, True))
367     {
368       BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
369       if (dont_descend && !isdots)
370         continue;
371           
372       if (isrootdir && isdots)
373         continue;
374
375       pstrcpy(pathreal,conn->dirpath);
376       if(needslash)
377         pstrcat(pathreal,"/");
378       pstrcat(pathreal,dname);
379       if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0) 
380       {
381         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
382         continue;
383       }
384
385       mode = dos_mode(conn,pathreal,&sbuf);
386
387       if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
388         DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
389         continue;
390       }
391
392       size = sbuf.st_size;
393       mdate = sbuf.st_mtime;
394       adate = sbuf.st_atime;
395       cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
396       if(mode & aDIR)
397         size = 0;
398
399       DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
400           
401       found = True;
402     }
403   }
404
405   name_map_mangle(fname,False,SNUM(conn));
406
407   p = pdata;
408   nameptr = p;
409
410   nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
411
412   switch (info_level)
413   {
414     case 1:
415       if(requires_resume_key) {
416         SIVAL(p,0,reskey);
417         p += 4;
418       }
419       put_dos_date2(p,l1_fdateCreation,cdate);
420       put_dos_date2(p,l1_fdateLastAccess,adate);
421       put_dos_date2(p,l1_fdateLastWrite,mdate);
422       SIVAL(p,l1_cbFile,(uint32)size);
423       SIVAL(p,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
424       SSVAL(p,l1_attrFile,mode);
425       SCVAL(p,l1_cchName,strlen(fname));
426       pstrcpy(p + l1_achName, fname);
427       nameptr = p + l1_achName;
428       p += l1_achName + strlen(fname) + 1;
429       break;
430
431     case 2:
432       /* info_level 2 */
433       if(requires_resume_key) {
434         SIVAL(p,0,reskey);
435         p += 4;
436       }
437       put_dos_date2(p,l2_fdateCreation,cdate);
438       put_dos_date2(p,l2_fdateLastAccess,adate);
439       put_dos_date2(p,l2_fdateLastWrite,mdate);
440       SIVAL(p,l2_cbFile,(uint32)size);
441       SIVAL(p,l2_cbFileAlloc,SMB_ROUNDUP(size,1024));
442       SSVAL(p,l2_attrFile,mode);
443       SIVAL(p,l2_cbList,0); /* No extended attributes */
444       SCVAL(p,l2_cchName,strlen(fname));
445       pstrcpy(p + l2_achName, fname);
446       nameptr = p + l2_achName;
447       p += l2_achName + strlen(fname) + 1;
448       break;
449
450     case 3:
451       SIVAL(p,0,reskey);
452       put_dos_date2(p,4,cdate);
453       put_dos_date2(p,8,adate);
454       put_dos_date2(p,12,mdate);
455       SIVAL(p,16,(uint32)size);
456       SIVAL(p,20,SMB_ROUNDUP(size,1024));
457       SSVAL(p,24,mode);
458       SIVAL(p,26,4);
459       CVAL(p,30) = strlen(fname);
460       pstrcpy(p+31, fname);
461       nameptr = p+31;
462       p += 31 + strlen(fname) + 1;
463       break;
464
465     case 4:
466       if(requires_resume_key) {
467         SIVAL(p,0,reskey);
468         p += 4;
469       }
470       SIVAL(p,0,33+strlen(fname)+1);
471       put_dos_date2(p,4,cdate);
472       put_dos_date2(p,8,adate);
473       put_dos_date2(p,12,mdate);
474       SIVAL(p,16,(uint32)size);
475       SIVAL(p,20,SMB_ROUNDUP(size,1024));
476       SSVAL(p,24,mode);
477       CVAL(p,32) = strlen(fname);
478       pstrcpy(p + 33, fname);
479       nameptr = p+33;
480       p += 33 + strlen(fname) + 1;
481       break;
482
483     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
484       was_8_3 = is_8_3(fname, True);
485       len = 94+strlen(fname);
486       len = (len + 3) & ~3;
487       SIVAL(p,0,len); p += 4;
488       SIVAL(p,0,reskey); p += 4;
489       put_long_date(p,cdate); p += 8;
490       put_long_date(p,adate); p += 8;
491       put_long_date(p,mdate); p += 8;
492       put_long_date(p,mdate); p += 8;
493       SOFF_T(p,0,size);
494       SOFF_T(p,8,size);
495       p += 16;
496       SIVAL(p,0,nt_extmode); p += 4;
497       SIVAL(p,0,strlen(fname)); p += 4;
498       SIVAL(p,0,0); p += 4;
499       if (!was_8_3) {
500         pstrcpy(p+2,fname);
501         if (!name_map_mangle(p+2,True,SNUM(conn)))
502           (p+2)[12] = 0;
503       } else
504         *(p+2) = 0;
505       strupper(p+2);
506       SSVAL(p,0,strlen(p+2));
507       p += 2 + 24;
508       /* nameptr = p;  */
509       pstrcpy(p,fname); p += strlen(p);
510       p = pdata + len;
511       break;
512
513     case SMB_FIND_FILE_DIRECTORY_INFO:
514       len = 64+strlen(fname);
515       len = (len + 3) & ~3;
516       SIVAL(p,0,len); p += 4;
517       SIVAL(p,0,reskey); p += 4;
518       put_long_date(p,cdate); p += 8;
519       put_long_date(p,adate); p += 8;
520       put_long_date(p,mdate); p += 8;
521       put_long_date(p,mdate); p += 8;
522       SOFF_T(p,0,size);
523       SOFF_T(p,8,size);
524       p += 16;
525       SIVAL(p,0,nt_extmode); p += 4;
526       SIVAL(p,0,strlen(fname)); p += 4;
527       pstrcpy(p,fname);
528       p = pdata + len;
529       break;
530       
531       
532     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
533       len = 68+strlen(fname);
534       len = (len + 3) & ~3;
535       SIVAL(p,0,len); p += 4;
536       SIVAL(p,0,reskey); p += 4;
537       put_long_date(p,cdate); p += 8;
538       put_long_date(p,adate); p += 8;
539       put_long_date(p,mdate); p += 8;
540       put_long_date(p,mdate); p += 8;
541       SOFF_T(p,0,size); 
542       SOFF_T(p,8,size);
543       p += 16;
544       SIVAL(p,0,nt_extmode); p += 4;
545       SIVAL(p,0,strlen(fname)); p += 4;
546       SIVAL(p,0,0); p += 4;
547       pstrcpy(p,fname);
548       p = pdata + len;
549       break;
550
551     case SMB_FIND_FILE_NAMES_INFO:
552       len = 12+strlen(fname);
553       len = (len + 3) & ~3;
554       SIVAL(p,0,len); p += 4;
555       SIVAL(p,0,reskey); p += 4;
556       SIVAL(p,0,strlen(fname)); p += 4;
557       pstrcpy(p,fname);
558       p = pdata + len;
559       break;
560
561     default:      
562       return(False);
563     }
564
565
566   if (PTR_DIFF(p,pdata) > space_remaining) {
567     /* Move the dirptr back to prev_dirpos */
568     SeekDir(conn->dirptr, prev_dirpos);
569     *out_of_space = True;
570     DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
571     return False; /* Not finished - just out of space */
572   }
573
574   /* Setup the last_filename pointer, as an offset from base_data */
575   *last_name_off = PTR_DIFF(nameptr,base_data);
576   /* Advance the data pointer to the next slot */
577   *ppdata = p;
578   return(found);
579 }
580   
581 /****************************************************************************
582  Convert the directory masks formated for the wire.
583 ****************************************************************************/
584
585 void mask_convert( char *mask)
586 {
587   /*
588    * We know mask is a pstring.
589    */
590   char *p = mask;
591   while (*p) {
592     if (*p == '<') {
593       pstring expnd;
594       if(p[1] != '"' && p[1] != '.') {
595         pstrcpy( expnd, p+1 );
596         *p++ = '*';
597         *p = '.';
598         safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2);
599       } else
600         *p = '*';
601     }
602     if (*p == '>') *p = '?';
603     if (*p == '"') *p = '.';
604     p++;
605   }
606 }
607
608 /****************************************************************************
609   reply to a TRANS2_FINDFIRST
610 ****************************************************************************/
611 static int call_trans2findfirst(connection_struct *conn,
612                                 char *inbuf, char *outbuf, int bufsize,  
613                                 char **pparams, char **ppdata)
614 {
615   /* We must be careful here that we don't return more than the
616      allowed number of data bytes. If this means returning fewer than
617      maxentries then so be it. We assume that the redirector has
618      enough room for the fixed number of parameter bytes it has
619      requested. */
620   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
621   char *params = *pparams;
622   char *pdata = *ppdata;
623   int dirtype = SVAL(params,0);
624   int maxentries = SVAL(params,2);
625   BOOL close_after_first = BITSETW(params+4,0);
626   BOOL close_if_end = BITSETW(params+4,1);
627   BOOL requires_resume_key = BITSETW(params+4,2);
628   int info_level = SVAL(params,6);
629   pstring directory;
630   pstring mask;
631   char *p, *wcard;
632   int last_name_off=0;
633   int dptr_num = -1;
634   int numentries = 0;
635   int i;
636   BOOL finished = False;
637   BOOL dont_descend = False;
638   BOOL out_of_space = False;
639   int space_remaining;
640   BOOL bad_path = False;
641
642   *directory = *mask = 0;
643
644   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",
645            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
646            info_level, max_data_bytes));
647   
648   switch (info_level) 
649     {
650     case 1:
651     case 2:
652     case 3:
653     case 4:
654     case SMB_FIND_FILE_DIRECTORY_INFO:
655     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
656     case SMB_FIND_FILE_NAMES_INFO:
657     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
658       break;
659     default:
660       return(ERROR(ERRDOS,ERRunknownlevel));
661     }
662
663   pstrcpy(directory, params + 12); /* Complete directory path with 
664                                      wildcard mask appended */
665
666   DEBUG(5,("path=%s\n",directory));
667
668   unix_convert(directory,conn,0,&bad_path,NULL);
669   if(!check_name(directory,conn)) {
670     if((errno == ENOENT) && bad_path)
671     {
672       unix_ERR_class = ERRDOS;
673       unix_ERR_code = ERRbadpath;
674     }
675
676 #if 0
677     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
678     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
679        (get_remote_arch() == RA_WINNT))
680     {
681       unix_ERR_class = ERRDOS;
682       unix_ERR_code = ERRbaddirectory;
683     }
684 #endif 
685
686     return(UNIXERROR(ERRDOS,ERRbadpath));
687   }
688
689   p = strrchr(directory,'/');
690   if(p == NULL) {
691     pstrcpy(mask,directory);
692     pstrcpy(directory,"./");
693   } else {
694     pstrcpy(mask,p+1);
695     *p = 0;
696   }
697
698   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
699
700   pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
701   if(!*ppdata)
702     return(ERROR(ERRDOS,ERRnomem));
703   bzero(pdata,max_data_bytes);
704
705   /* Realloc the params space */
706   params = *pparams = Realloc(*pparams, 10);
707   if(params == NULL)
708     return(ERROR(ERRDOS,ERRnomem));
709
710   dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
711   if (dptr_num < 0)
712     return(UNIXERROR(ERRDOS,ERRbadfile));
713
714   /* Convert the formatted mask. */
715   mask_convert(mask);
716
717 #if 0 /* JRA */
718   /*
719    * Now we have a working mask_match in util.c, I believe
720    * we no longer need these hacks (in fact they break
721    * things). JRA. 
722    */
723
724   /* a special case for 16 bit apps */
725   if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
726
727   /* handle broken clients that send us old 8.3 format */
728   string_sub(mask,"????????","*");
729   string_sub(mask,".???",".*");
730 #endif /* JRA */
731
732   /* Save the wildcard match and attribs we are using on this directory - 
733      needed as lanman2 assumes these are being saved between calls */
734
735   if(!(wcard = strdup(mask))) {
736     dptr_close(dptr_num);
737     return(ERROR(ERRDOS,ERRnomem));
738   }
739
740   dptr_set_wcard(dptr_num, wcard);
741   dptr_set_attr(dptr_num, dirtype);
742
743   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
744
745   /* We don't need to check for VOL here as this is returned by 
746      a different TRANS2 call. */
747   
748   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
749            conn->dirpath,lp_dontdescend(SNUM(conn))));
750   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
751     dont_descend = True;
752     
753   p = pdata;
754   space_remaining = max_data_bytes;
755   out_of_space = False;
756
757   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
758     {
759
760       /* this is a heuristic to avoid seeking the dirptr except when 
761          absolutely necessary. It allows for a filename of about 40 chars */
762       if (space_remaining < DIRLEN_GUESS && numentries > 0)
763         {
764           out_of_space = True;
765           finished = False;
766         }
767       else
768         {
769           finished = 
770             !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
771                                    requires_resume_key,dont_descend,
772                                    &p,pdata,space_remaining, &out_of_space,
773                                    &last_name_off);
774         }
775
776       if (finished && out_of_space)
777         finished = False;
778
779       if (!finished && !out_of_space)
780         numentries++;
781       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
782     }
783   
784   /* Check if we can close the dirptr */
785   if(close_after_first || (finished && close_if_end))
786     {
787       dptr_close(dptr_num);
788       DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
789       dptr_num = -1;
790     }
791
792   /* 
793    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
794    * from observation of NT.
795    */
796
797   if(numentries == 0)
798     return(ERROR(ERRDOS,ERRbadfile));
799
800   /* At this point pdata points to numentries directory entries. */
801
802   /* Set up the return parameter block */
803   SSVAL(params,0,dptr_num);
804   SSVAL(params,2,numentries);
805   SSVAL(params,4,finished);
806   SSVAL(params,6,0); /* Never an EA error */
807   SSVAL(params,8,last_name_off);
808
809   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
810
811   if ((! *directory) && dptr_path(dptr_num))
812     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
813
814   DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
815             smb_fn_name(CVAL(inbuf,smb_com)), 
816             mask, directory, dirtype, numentries ) );
817
818   return(-1);
819 }
820
821
822 /****************************************************************************
823   reply to a TRANS2_FINDNEXT
824 ****************************************************************************/
825 static int call_trans2findnext(connection_struct *conn, 
826                                char *inbuf, char *outbuf, 
827                                int length, int bufsize,
828                                char **pparams, char **ppdata)
829 {
830   /* We must be careful here that we don't return more than the
831      allowed number of data bytes. If this means returning fewer than
832      maxentries then so be it. We assume that the redirector has
833      enough room for the fixed number of parameter bytes it has
834      requested. */
835   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
836   char *params = *pparams;
837   char *pdata = *ppdata;
838   int16 dptr_num = SVAL(params,0);
839   int maxentries = SVAL(params,2);
840   uint16 info_level = SVAL(params,4);
841   uint32 resume_key = IVAL(params,6);
842   BOOL close_after_request = BITSETW(params+10,0);
843   BOOL close_if_end = BITSETW(params+10,1);
844   BOOL requires_resume_key = BITSETW(params+10,2);
845   BOOL continue_bit = BITSETW(params+10,3);
846   pstring resume_name;
847   pstring mask;
848   pstring directory;
849   char *p;
850   uint16 dirtype;
851   int numentries = 0;
852   int i, last_name_off=0;
853   BOOL finished = False;
854   BOOL dont_descend = False;
855   BOOL out_of_space = False;
856   int space_remaining;
857
858   *mask = *directory = *resume_name = 0;
859
860   pstrcpy( resume_name, params+12);
861
862   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
863 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
864 resume_key = %d resume name = %s continue=%d level = %d\n",
865            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
866            requires_resume_key, resume_key, resume_name, continue_bit, info_level));
867
868   switch (info_level) 
869     {
870     case 1:
871     case 2:
872     case 3:
873     case 4:
874     case SMB_FIND_FILE_DIRECTORY_INFO:
875     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
876     case SMB_FIND_FILE_NAMES_INFO:
877     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
878       break;
879     default:
880       return(ERROR(ERRDOS,ERRunknownlevel));
881     }
882
883   pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
884   if(!*ppdata)
885     return(ERROR(ERRDOS,ERRnomem));
886   bzero(pdata,max_data_bytes);
887
888   /* Realloc the params space */
889   params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
890   if(!params)
891     return(ERROR(ERRDOS,ERRnomem));
892
893   /* Check that the dptr is valid */
894   if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
895     return(ERROR(ERRDOS,ERRnofiles));
896
897   string_set(&conn->dirpath,dptr_path(dptr_num));
898
899   /* Get the wildcard mask from the dptr */
900   if((p = dptr_wcard(dptr_num))== NULL) {
901     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
902     return (ERROR(ERRDOS,ERRnofiles));
903   }
904   pstrcpy(mask, p);
905   pstrcpy(directory,conn->dirpath);
906
907   /* Get the attr mask from the dptr */
908   dirtype = dptr_attr(dptr_num);
909
910   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
911            dptr_num, mask, dirtype, 
912            (long)conn->dirptr,
913            TellDir(conn->dirptr)));
914
915   /* We don't need to check for VOL here as this is returned by 
916      a different TRANS2 call. */
917
918   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
919   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
920     dont_descend = True;
921     
922   p = pdata;
923   space_remaining = max_data_bytes;
924   out_of_space = False;
925
926   /* 
927    * Seek to the correct position. We no longer use the resume key but
928    * depend on the last file name instead.
929    */
930   if(requires_resume_key && *resume_name && !continue_bit)
931   {
932     /*
933      * Fix for NT redirector problem triggered by resume key indexes
934      * changing between directory scans. We now return a resume key of 0
935      * and instead look for the filename to continue from (also given
936      * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
937      * findfirst/findnext (as is usual) then the directory pointer
938      * should already be at the correct place. Check this by scanning
939      * backwards looking for an exact (ie. case sensitive) filename match. 
940      * If we get to the beginning of the directory and haven't found it then scan
941      * forwards again looking for a match. JRA.
942      */
943
944     int current_pos, start_pos;
945     char *dname = NULL;
946     void *dirptr = conn->dirptr;
947     start_pos = TellDir(dirptr);
948     for(current_pos = start_pos; current_pos >= 0; current_pos--)
949     {
950       DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
951
952       SeekDir(dirptr, current_pos);
953       dname = ReadDirName(dirptr);
954
955       /*
956        * Remember, name_map_mangle is called by
957        * get_lanman2_dir_entry(), so the resume name
958        * could be mangled. Ensure we do the same
959        * here.
960        */
961
962       if(dname != NULL)
963         name_map_mangle( dname, False, SNUM(conn));
964
965       if(dname && strcsequal( resume_name, dname))
966       {
967         SeekDir(dirptr, current_pos+1);
968         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
969         break;
970       }
971     }
972
973     /*
974      * Scan forward from start if not found going backwards.
975      */
976
977     if(current_pos < 0)
978     {
979       DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
980       SeekDir(dirptr, start_pos);
981       for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
982       {
983         /*
984          * Remember, name_map_mangle is called by
985          * get_lanman2_dir_entry(), so the resume name
986          * could be mangled. Ensure we do the same
987          * here.
988          */
989
990         if(dname != NULL)
991           name_map_mangle( dname, False, SNUM(conn));
992
993         if(dname && strcsequal( resume_name, dname))
994         {
995           SeekDir(dirptr, current_pos+1);
996           DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
997           break;
998         }
999       } /* end for */
1000     } /* end if current_pos */
1001   } /* end if requires_resume_key && !continue_bit */
1002
1003   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1004     {
1005       /* this is a heuristic to avoid seeking the dirptr except when 
1006          absolutely necessary. It allows for a filename of about 40 chars */
1007       if (space_remaining < DIRLEN_GUESS && numentries > 0)
1008         {
1009           out_of_space = True;
1010           finished = False;
1011         }
1012       else
1013         {
1014           finished = 
1015             !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1016                                    requires_resume_key,dont_descend,
1017                                    &p,pdata,space_remaining, &out_of_space,
1018                                    &last_name_off);
1019         }
1020
1021       if (finished && out_of_space)
1022         finished = False;
1023
1024       if (!finished && !out_of_space)
1025         numentries++;
1026       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1027     }
1028   
1029   /* Check if we can close the dirptr */
1030   if(close_after_request || (finished && close_if_end))
1031     {
1032       dptr_close(dptr_num); /* This frees up the saved mask */
1033       DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1034       dptr_num = -1;
1035     }
1036
1037
1038   /* Set up the return parameter block */
1039   SSVAL(params,0,numentries);
1040   SSVAL(params,2,finished);
1041   SSVAL(params,4,0); /* Never an EA error */
1042   SSVAL(params,6,last_name_off);
1043
1044   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1045
1046   if ((! *directory) && dptr_path(dptr_num))
1047     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1048
1049   DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1050             smb_fn_name(CVAL(inbuf,smb_com)), 
1051             mask, directory, dirtype, numentries ) );
1052
1053   return(-1);
1054 }
1055
1056 /****************************************************************************
1057   reply to a TRANS2_QFSINFO (query filesystem info)
1058 ****************************************************************************/
1059
1060 static int call_trans2qfsinfo(connection_struct *conn, 
1061                               char *inbuf, char *outbuf, 
1062                               int length, int bufsize,
1063                               char **pparams, char **ppdata)
1064 {
1065   char *pdata = *ppdata;
1066   char *params = *pparams;
1067   uint16 info_level = SVAL(params,0);
1068   int data_len;
1069   SMB_STRUCT_STAT st;
1070   char *vname = volume_label(SNUM(conn));
1071   int snum = SNUM(conn);
1072   char *fstype = lp_fstype(SNUM(conn));
1073   extern uint32 global_client_caps;
1074
1075   DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1076
1077   if(conn->vfs_ops.stat(".",&st)!=0) {
1078     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1079     return (ERROR(ERRSRV,ERRinvdevice));
1080   }
1081
1082   pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1083
1084   switch (info_level) 
1085   {
1086     case 1:
1087     {
1088       SMB_BIG_UINT dfree,dsize,bsize;
1089       data_len = 18;
1090       conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);        
1091       SIVAL(pdata,l1_idFileSystem,st.st_dev);
1092       SIVAL(pdata,l1_cSectorUnit,bsize/512);
1093       SIVAL(pdata,l1_cUnit,dsize);
1094       SIVAL(pdata,l1_cUnitAvail,dfree);
1095       SSVAL(pdata,l1_cbSector,512);
1096       DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1097                  (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1098          (unsigned int)dfree, 512));
1099       break;
1100     }
1101     case 2:
1102     { 
1103       /* Return volume name */
1104       int volname_len = MIN(strlen(vname),11);
1105       data_len = l2_vol_szVolLabel + volname_len + 1;
1106       /* 
1107        * Add volume serial number - hash of a combination of
1108        * the called hostname and the service name.
1109        */
1110       SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1111       SCVAL(pdata,l2_vol_cch,volname_len);
1112       StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1113       DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1114                (unsigned)st.st_ctime, volname_len,
1115                pdata+l2_vol_szVolLabel));
1116       break;
1117     }
1118     case SMB_QUERY_FS_ATTRIBUTE_INFO:
1119       data_len = 12 + 2*strlen(fstype);
1120       SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH); /* FS ATTRIBUTES */
1121 #if 0 /* Old code. JRA. */
1122       SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1123 #endif /* Old code. */
1124       SIVAL(pdata,4,128); /* Max filename component length */
1125       SIVAL(pdata,8,2*strlen(fstype));
1126       ascii_to_unibuf(pdata+12, fstype, 1024-2-12);
1127       SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1128       break;
1129     case SMB_QUERY_FS_LABEL_INFO:
1130       data_len = 4 + strlen(vname);
1131       SIVAL(pdata,0,strlen(vname));
1132       pstrcpy(pdata+4,vname);      
1133       break;
1134     case SMB_QUERY_FS_VOLUME_INFO:      
1135
1136       /* 
1137        * Add volume serial number - hash of a combination of
1138        * the called hostname and the service name.
1139        */
1140       SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1141             (str_checksum(local_machine)<<16));
1142
1143       /* NT4 always serves this up as unicode but expects it to be
1144        * delivered as ascii! (tridge && JRA)
1145        */
1146       if (global_client_caps & CAP_NT_SMBS) {
1147               data_len = 18 + strlen(vname);
1148               SIVAL(pdata,12,strlen(vname));
1149               pstrcpy(pdata+18,vname);      
1150       } else {
1151               data_len = 18 + 2*strlen(vname);
1152               SIVAL(pdata,12,strlen(vname)*2);
1153               ascii_to_unibuf(pdata+18, vname, 1024-2-18);
1154       }
1155
1156       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", 
1157                strlen(vname),vname));
1158       break;
1159     case SMB_QUERY_FS_SIZE_INFO:
1160     {
1161       SMB_BIG_UINT dfree,dsize,bsize;
1162       data_len = 24;
1163       conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);        
1164       SIVAL(pdata,0,dsize);
1165       SIVAL(pdata,8,dfree);
1166       SIVAL(pdata,16,bsize/512);
1167       SIVAL(pdata,20,512);
1168       break;
1169     }
1170     case SMB_QUERY_FS_DEVICE_INFO:
1171       data_len = 8;
1172       SIVAL(pdata,0,0); /* dev type */
1173       SIVAL(pdata,4,0); /* characteristics */
1174       break;
1175     case SMB_MAC_QUERY_FS_INFO:
1176             /*
1177              * Thursby MAC extension... ONLY on NTFS filesystems
1178              * once we do streams then we don't need this
1179              */
1180             if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1181                     data_len = 88;
1182                     SIVAL(pdata,84,0x100); /* Don't support mac... */
1183                     break;
1184             }
1185             /* drop through */
1186     default:
1187       return(ERROR(ERRDOS,ERRunknownlevel));
1188   }
1189
1190
1191   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1192
1193   DEBUG( 4, ( "%s info_level = %d\n",
1194             smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1195
1196   return -1;
1197 }
1198
1199 /****************************************************************************
1200   reply to a TRANS2_SETFSINFO (set filesystem info)
1201 ****************************************************************************/
1202 static int call_trans2setfsinfo(connection_struct *conn,
1203                                 char *inbuf, char *outbuf, int length, 
1204                                 int bufsize,
1205                                 char **pparams, char **ppdata)
1206 {
1207   /* Just say yes we did it - there is nothing that
1208      can be set here so it doesn't matter. */
1209   int outsize;
1210   DEBUG(3,("call_trans2setfsinfo\n"));
1211
1212   if (!CAN_WRITE(conn))
1213     return(ERROR(ERRSRV,ERRaccess));
1214
1215   outsize = set_message(outbuf,10,0,True);
1216
1217   return outsize;
1218 }
1219
1220 /****************************************************************************
1221   Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1222   file name or file id).
1223 ****************************************************************************/
1224
1225 static int call_trans2qfilepathinfo(connection_struct *conn,
1226                                     char *inbuf, char *outbuf, int length, 
1227                                     int bufsize,
1228                                     char **pparams,char **ppdata,
1229                                     int total_data)
1230 {
1231   char *params = *pparams;
1232   char *pdata = *ppdata;
1233   uint16 tran_call = SVAL(inbuf, smb_setup0);
1234   uint16 info_level;
1235   int mode=0;
1236   SMB_OFF_T size=0;
1237   unsigned int data_size;
1238   SMB_STRUCT_STAT sbuf;
1239   pstring fname1;
1240   char *fname;
1241   char *p;
1242   int l;
1243   SMB_OFF_T pos = 0;
1244   BOOL bad_path = False;
1245   BOOL delete_pending = False;
1246
1247   if (tran_call == TRANSACT2_QFILEINFO) {
1248     files_struct *fsp = file_fsp(params,0);
1249     info_level = SVAL(params,2);
1250
1251     if(fsp && fsp->open && fsp->is_directory) {
1252       /*
1253        * This is actually a QFILEINFO on a directory
1254        * handle (returned from an NT SMB). NT5.0 seems
1255        * to do this call. JRA.
1256        */
1257       fname = fsp->fsp_name;
1258       unix_convert(fname,conn,0,&bad_path,&sbuf);
1259       if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && 
1260           conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) {
1261         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1262         if((errno == ENOENT) && bad_path)
1263         {
1264           unix_ERR_class = ERRDOS;
1265           unix_ERR_code = ERRbadpath;
1266         }
1267         return(UNIXERROR(ERRDOS,ERRbadpath));
1268       }
1269     } else {
1270       /*
1271        * Original code - this is an open file.
1272        */
1273       CHECK_FSP(fsp,conn);
1274       CHECK_ERROR(fsp);
1275
1276       fname = fsp->fsp_name;
1277       if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1278         DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1279         return(UNIXERROR(ERRDOS,ERRbadfid));
1280       }
1281       if((pos = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
1282         return(UNIXERROR(ERRDOS,ERRnoaccess));
1283
1284       delete_pending = fsp->fd_ptr->delete_on_close;
1285     }
1286   } else {
1287     /* qpathinfo */
1288     info_level = SVAL(params,0);
1289     fname = &fname1[0];
1290     pstrcpy(fname,&params[6]);
1291     unix_convert(fname,conn,0,&bad_path,&sbuf);
1292     if (!check_name(fname,conn) || 
1293         (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),
1294                                                  &sbuf))) {
1295       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1296       if((errno == ENOENT) && bad_path)
1297       {
1298         unix_ERR_class = ERRDOS;
1299         unix_ERR_code = ERRbadpath;
1300       }
1301       return(UNIXERROR(ERRDOS,ERRbadpath));
1302     }
1303   }
1304
1305
1306   DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1307            fname,info_level,tran_call,total_data));
1308
1309   p = strrchr(fname,'/'); 
1310   if (!p) 
1311     p = fname;
1312   else
1313     p++;
1314   l = strlen(p);  
1315   mode = dos_mode(conn,fname,&sbuf);
1316   size = sbuf.st_size;
1317   if (mode & aDIR) size = 0;
1318
1319   /* from now on we only want the part after the / */
1320   fname = p;
1321   
1322   params = *pparams = Realloc(*pparams,2); bzero(params,2);
1323   data_size = 1024;
1324   pdata = *ppdata = Realloc(*ppdata, data_size); 
1325
1326   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1327     /* uggh, EAs for OS2 */
1328     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1329     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1330   }
1331
1332   bzero(pdata,data_size);
1333
1334   switch (info_level) 
1335     {
1336     case SMB_INFO_STANDARD:
1337     case SMB_INFO_QUERY_EA_SIZE:
1338       data_size = (info_level==1?22:26);
1339       put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1340       put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1341       put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1342       SIVAL(pdata,l1_cbFile,(uint32)size);
1343       SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
1344       SSVAL(pdata,l1_attrFile,mode);
1345       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1346       break;
1347
1348     case SMB_INFO_QUERY_EAS_FROM_LIST:
1349       data_size = 24;
1350       put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1351       put_dos_date2(pdata,4,sbuf.st_atime);
1352       put_dos_date2(pdata,8,sbuf.st_mtime);
1353       SIVAL(pdata,12,(uint32)size);
1354       SIVAL(pdata,16,SMB_ROUNDUP(size,1024));
1355       SIVAL(pdata,20,mode);
1356       break;
1357
1358     case SMB_INFO_QUERY_ALL_EAS:
1359       data_size = 4;
1360       SIVAL(pdata,0,data_size);
1361       break;
1362
1363     case 6:
1364       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
1365
1366     case SMB_QUERY_FILE_BASIC_INFO:
1367       data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1368       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1369       put_long_date(pdata+8,sbuf.st_atime);
1370       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1371       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1372       SIVAL(pdata,32,mode);
1373
1374       DEBUG(5,("SMB_QFBI - "));
1375       {
1376         time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1377         DEBUG(5,("create: %s ", ctime(&create_time)));
1378       }
1379       DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1380       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1381       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1382       DEBUG(5,("mode: %x\n", mode));
1383
1384       break;
1385
1386     case SMB_QUERY_FILE_STANDARD_INFO:
1387       data_size = 22;
1388       SOFF_T(pdata,0,size);
1389       SOFF_T(pdata,8,size);
1390       SIVAL(pdata,16,sbuf.st_nlink);
1391       CVAL(pdata,20) = 0;
1392       CVAL(pdata,21) = (mode&aDIR)?1:0;
1393       break;
1394
1395     case SMB_QUERY_FILE_EA_INFO:
1396       data_size = 4;
1397       break;
1398
1399     /* Get the 8.3 name - used if NT SMB was negotiated. */
1400     case SMB_QUERY_FILE_ALT_NAME_INFO:
1401       {
1402         pstring short_name;
1403         char *data_end;
1404
1405         pstrcpy(short_name,p);
1406         /* Mangle if not already 8.3 */
1407         if(!is_8_3(short_name, True))
1408         {
1409           if(!name_map_mangle(short_name,True,SNUM(conn)))
1410             *short_name = '\0';
1411         }
1412         strupper(short_name);
1413         data_end = ascii_to_unibuf(pdata + 4, short_name, 1024-2-4);
1414         data_size = data_end - pdata;
1415         SIVAL(pdata,0,2*(data_size-4));
1416       }
1417       break;
1418
1419     case SMB_QUERY_FILE_NAME_INFO:
1420       data_size = 4 + l;
1421       SIVAL(pdata,0,l);
1422       pstrcpy(pdata+4,fname);
1423       break;
1424
1425     case SMB_QUERY_FILE_ALLOCATION_INFO:
1426     case SMB_QUERY_FILE_END_OF_FILEINFO:
1427       data_size = 8;
1428       SOFF_T(pdata,0,size);
1429       break;
1430
1431     case SMB_QUERY_FILE_ALL_INFO:
1432       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1433       put_long_date(pdata+8,sbuf.st_atime);
1434       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1435       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1436       SIVAL(pdata,32,mode);
1437       pdata += 40;
1438       SOFF_T(pdata,0,size);
1439       SOFF_T(pdata,8,size);
1440       SIVAL(pdata,16,sbuf.st_nlink);
1441       CVAL(pdata,20) = delete_pending;
1442       CVAL(pdata,21) = (mode&aDIR)?1:0;
1443       pdata += 24;
1444       SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); 
1445       pdata += 8; /* index number */
1446       pdata += 4; /* EA info */
1447       if (mode & aRONLY)
1448         SIVAL(pdata,0,0xA9);
1449       else
1450         SIVAL(pdata,0,0xd01BF);
1451       pdata += 4;
1452       SOFF_T(pdata,0,pos); /* current offset */
1453       pdata += 8;
1454       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1455       pdata += 4;
1456       pdata += 4; /* alignment */
1457       SIVAL(pdata,0,l);
1458       pstrcpy(pdata+4,fname);
1459       pdata += 4 + l;
1460       data_size = PTR_DIFF(pdata,(*ppdata));
1461       break;
1462
1463 #if 0
1464       /* NT4 server just returns "invalid query" to this - if we try to answer 
1465          it then NTws gets a BSOD! (tridge) */
1466     case SMB_QUERY_FILE_STREAM_INFO:
1467       data_size = 24 + l;
1468       SIVAL(pdata,0,pos);
1469       SIVAL(pdata,4,size);
1470       SIVAL(pdata,12,size);
1471       SIVAL(pdata,20,l);        
1472       pstrcpy(pdata+24,fname);
1473       break;
1474 #endif
1475
1476     default:
1477       return(ERROR(ERRDOS,ERRunknownlevel));
1478     }
1479
1480   send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1481
1482   return(-1);
1483 }
1484
1485 /****************************************************************************
1486   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1487 ****************************************************************************/
1488 static int call_trans2setfilepathinfo(connection_struct *conn,
1489                                       char *inbuf, char *outbuf, int length, 
1490                                       int bufsize, char **pparams, 
1491                                       char **ppdata, int total_data)
1492 {
1493   char *params = *pparams;
1494   char *pdata = *ppdata;
1495   uint16 tran_call = SVAL(inbuf, smb_setup0);
1496   uint16 info_level;
1497   int mode=0;
1498   SMB_OFF_T size=0;
1499   struct utimbuf tvs;
1500   SMB_STRUCT_STAT st;
1501   pstring fname1;
1502   char *fname;
1503   int fd = -1;
1504   BOOL bad_path = False;
1505   files_struct *fsp = NULL;
1506
1507   if (!CAN_WRITE(conn))
1508     return(ERROR(ERRSRV,ERRaccess));
1509
1510   if (tran_call == TRANSACT2_SETFILEINFO) {
1511     fsp = file_fsp(params,0);
1512     info_level = SVAL(params,2);    
1513
1514     if(fsp && fsp->open && fsp->is_directory) {
1515       /*
1516        * This is actually a SETFILEINFO on a directory
1517        * handle (returned from an NT SMB). NT5.0 seems
1518        * to do this call. JRA.
1519        */
1520       fname = fsp->fsp_name;
1521       unix_convert(fname,conn,0,&bad_path,&st);
1522       if (!check_name(fname,conn) || (!VALID_STAT(st) && 
1523                                       conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) {
1524         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1525         if((errno == ENOENT) && bad_path)
1526         {
1527           unix_ERR_class = ERRDOS;
1528           unix_ERR_code = ERRbadpath;
1529         }
1530         return(UNIXERROR(ERRDOS,ERRbadpath));
1531       }
1532     } else {
1533       /*
1534        * Original code - this is an open file.
1535        */
1536       CHECK_FSP(fsp,conn);
1537       CHECK_ERROR(fsp);
1538
1539       fname = fsp->fsp_name;
1540       fd = fsp->fd_ptr->fd;
1541
1542       if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) {
1543         DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1544         return(UNIXERROR(ERRDOS,ERRbadfid));
1545       }
1546     }
1547   } else {
1548     /* set path info */
1549     info_level = SVAL(params,0);    
1550     fname = fname1;
1551     pstrcpy(fname,&params[6]);
1552     unix_convert(fname,conn,0,&bad_path,&st);
1553     if(!check_name(fname, conn))
1554     {
1555       if((errno == ENOENT) && bad_path)
1556       {
1557         unix_ERR_class = ERRDOS;
1558         unix_ERR_code = ERRbadpath;
1559       }
1560       return(UNIXERROR(ERRDOS,ERRbadpath));
1561     }
1562  
1563     if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) {
1564       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1565       if((errno == ENOENT) && bad_path)
1566       {
1567         unix_ERR_class = ERRDOS;
1568         unix_ERR_code = ERRbadpath;
1569       }
1570       return(UNIXERROR(ERRDOS,ERRbadpath));
1571     }    
1572   }
1573
1574   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1575            tran_call,fname,info_level,total_data));
1576
1577   /* Realloc the parameter and data sizes */
1578   params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1579   if(params == NULL)
1580     return(ERROR(ERRDOS,ERRnomem));
1581
1582   size = st.st_size;
1583   tvs.modtime = st.st_mtime;
1584   tvs.actime = st.st_atime;
1585   mode = dos_mode(conn,fname,&st);
1586
1587   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1588     /* uggh, EAs for OS2 */
1589     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1590     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1591   }
1592
1593   switch (info_level)
1594   {
1595     case SMB_INFO_STANDARD:
1596     case SMB_INFO_QUERY_EA_SIZE:
1597     {
1598       /* access time */
1599       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1600
1601       /* write time */
1602       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1603
1604       mode = SVAL(pdata,l1_attrFile);
1605       size = IVAL(pdata,l1_cbFile);
1606       break;
1607     }
1608
1609     /* XXXX um, i don't think this is right.
1610        it's also not in the cifs6.txt spec.
1611      */
1612     case SMB_INFO_QUERY_EAS_FROM_LIST:
1613       tvs.actime = make_unix_date2(pdata+8);
1614       tvs.modtime = make_unix_date2(pdata+12);
1615       size = IVAL(pdata,16);
1616       mode = IVAL(pdata,24);
1617       break;
1618
1619     /* XXXX nor this.  not in cifs6.txt, either. */
1620     case SMB_INFO_QUERY_ALL_EAS:
1621       tvs.actime = make_unix_date2(pdata+8);
1622       tvs.modtime = make_unix_date2(pdata+12);
1623       size = IVAL(pdata,16);
1624       mode = IVAL(pdata,24);
1625       break;
1626
1627     case SMB_SET_FILE_BASIC_INFO:
1628     {
1629       /* Ignore create time at offset pdata. */
1630
1631       /* access time */
1632       tvs.actime = interpret_long_date(pdata+8);
1633
1634       /* write time + changed time, combined. */
1635       tvs.modtime=MAX(interpret_long_date(pdata+16),
1636                       interpret_long_date(pdata+24));
1637
1638 #if 0 /* Needs more testing... */
1639       /* Test from Luke to prevent Win95 from
1640          setting incorrect values here.
1641        */
1642       if (tvs.actime < tvs.modtime)
1643         return(ERROR(ERRDOS,ERRnoaccess));
1644 #endif /* Needs more testing... */
1645
1646       /* attributes */
1647       mode = IVAL(pdata,32);
1648       break;
1649     }
1650
1651     case SMB_SET_FILE_END_OF_FILE_INFO:
1652     {
1653       size = IVAL(pdata,0);
1654 #ifdef LARGE_SMB_OFF_T
1655       size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1656 #else /* LARGE_SMB_OFF_T */
1657       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1658          return(ERROR(ERRDOS,ERRunknownlevel));
1659 #endif /* LARGE_SMB_OFF_T */
1660       break;
1661     }
1662
1663     case SMB_SET_FILE_ALLOCATION_INFO:
1664       break; /* We don't need to do anything for this call. */
1665
1666     case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1667     {
1668       if ((tran_call == TRANSACT2_SETFILEINFO) && (fsp != NULL))
1669       {
1670         BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
1671
1672         if(fsp->is_directory)
1673           return(ERROR(ERRDOS,ERRnoaccess));
1674
1675         /*
1676          * We can only set the delete on close flag if
1677          * the share mode contained ALLOW_SHARE_DELETE
1678          */
1679
1680         if(lp_share_modes(SNUM(conn)))
1681         {
1682           if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
1683             return(ERROR(ERRDOS,ERRnoaccess));
1684
1685           /*
1686            * If the flag has been set then
1687            * modify the share mode entry for all files we have open
1688            * on this device and inode to tell other smbds we have 
1689            * changed the delete on close flag.
1690            */
1691
1692           if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode))
1693           {
1694             int token;
1695             int i;
1696             files_struct *iterate_fsp;
1697             SMB_DEV_T dev = fsp->fd_ptr->dev;
1698             SMB_INO_T inode = fsp->fd_ptr->inode;
1699             int num_share_modes;
1700             share_mode_entry *current_shares = NULL;
1701
1702             if(lock_share_entry(fsp->conn, dev, inode, &token) == False)
1703               return(ERROR(ERRDOS,ERRnoaccess));
1704
1705             /*
1706              * Before we allow this we need to ensure that all current opens
1707              * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they
1708              * do not then we deny this (as we are essentially deleting the
1709              * file at this point.
1710              */
1711
1712             num_share_modes = get_share_modes(conn, token, dev, inode, &current_shares);
1713             for(i = 0; i < num_share_modes; i++)
1714             {
1715               if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode))
1716               {
1717                 DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \
1718 file %s as a share exists that was not opened with FILE_DELETE access.\n",
1719                       fsp->fnum, fsp->fsp_name ));
1720                 /*
1721                  * Release the lock.
1722                  */
1723
1724                 unlock_share_entry(fsp->conn, dev, inode, token);
1725
1726                 /*
1727                  * current_shares was malloced by get_share_modes - free it here.
1728                  */
1729
1730                 free((char *)current_shares);
1731
1732                 /*
1733                  * Even though share violation would be more appropriate here,
1734                  * return ERRnoaccess as that's what NT does.
1735                  */
1736
1737                 return(ERROR(ERRDOS,ERRnoaccess));
1738               }
1739             }
1740
1741             /*
1742              * current_shares was malloced by get_share_modes - free it here.
1743              */
1744
1745             free((char *)current_shares);
1746
1747             DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1748                  delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1749
1750             /*
1751              * Go through all files we have open on the same device and
1752              * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1753              * Other smbd's that have this file open will have to fend for themselves. We
1754              * take care of this (rare) case in close_file(). See the comment there.
1755              */
1756
1757             for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
1758                                   iterate_fsp = file_find_di_next(iterate_fsp))
1759             {
1760               int new_share_mode = (delete_on_close ? 
1761                                     (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
1762                                     (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
1763
1764               DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \
1765 dev = %x, inode = %.0f from %x to %x\n", 
1766                     iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, 
1767                     (double)inode, iterate_fsp->share_mode, new_share_mode ));
1768
1769               if(modify_share_mode(token, iterate_fsp, new_share_mode)==False)
1770                 DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
1771 dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
1772             }
1773
1774             /*
1775              * Set the delete on close flag in the reference
1776              * counted struct. Delete when the last reference
1777              * goes away.
1778              */
1779            fsp->fd_ptr->delete_on_close = delete_on_close;
1780            unlock_share_entry(fsp->conn, dev, inode, token);
1781
1782            DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1783                  delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1784
1785           } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */
1786         } /* end if lp_share_modes() */
1787
1788       } else
1789         return(ERROR(ERRDOS,ERRunknownlevel));
1790       break;
1791     }
1792
1793     default:
1794     {
1795       return(ERROR(ERRDOS,ERRunknownlevel));
1796     }
1797   }
1798
1799   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1800   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1801   DEBUG(6,("size: %.0f ", (double)size));
1802   DEBUG(6,("mode: %x\n"  , mode));
1803
1804   /* get some defaults (no modifications) if any info is zero. */
1805   if (!tvs.actime) tvs.actime = st.st_atime;
1806   if (!tvs.modtime) tvs.modtime = st.st_mtime;
1807   if (!size) size = st.st_size;
1808
1809   /* Try and set the times, size and mode of this file -
1810      if they are different from the current values
1811    */
1812   if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1813   {
1814     if(fsp != NULL)
1815     {
1816       /*
1817        * This was a setfileinfo on an open file.
1818        * NT does this a lot. It's actually pointless
1819        * setting the time here, as it will be overwritten
1820        * on the next write, so we save the request
1821        * away and will set it on file code. JRA.
1822        */
1823       fsp->pending_modtime = tvs.modtime;
1824     }
1825     else if(file_utime(conn, fname, &tvs)!=0)
1826     {
1827       return(UNIXERROR(ERRDOS,ERRnoaccess));
1828     }
1829   }
1830
1831   /* check the mode isn't different, before changing it */
1832   if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
1833   {
1834     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1835     return(UNIXERROR(ERRDOS,ERRnoaccess));
1836   }
1837
1838   if(size != st.st_size)
1839   {
1840     if (fd == -1)
1841     {
1842 DEBUG(0, ("@@@ 23 @@@\n"));
1843       fd = dos_open(fname,O_RDWR,0);
1844       if (fd == -1)
1845       {
1846         return(UNIXERROR(ERRDOS,ERRbadpath));
1847       }
1848       set_filelen(fd, size);
1849       close(fd);
1850     }
1851     else
1852     {
1853       set_filelen(fd, size);
1854     }
1855   }
1856
1857   SSVAL(params,0,0);
1858
1859   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1860   
1861   return(-1);
1862 }
1863
1864 /****************************************************************************
1865   reply to a TRANS2_MKDIR (make directory with extended attributes).
1866 ****************************************************************************/
1867 static int call_trans2mkdir(connection_struct *conn,
1868                             char *inbuf, char *outbuf, int length, int bufsize,
1869                             char **pparams, char **ppdata)
1870 {
1871   char *params = *pparams;
1872   pstring directory;
1873   int ret = -1;
1874   BOOL bad_path = False;
1875
1876   if (!CAN_WRITE(conn))
1877     return(ERROR(ERRSRV,ERRaccess));
1878
1879   pstrcpy(directory, &params[4]);
1880
1881   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1882
1883   unix_convert(directory,conn,0,&bad_path,NULL);
1884   if (check_name(directory,conn))
1885     ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
1886                               unix_mode(conn,aDIR));
1887   
1888   if(ret < 0)
1889     {
1890       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1891       if((errno == ENOENT) && bad_path)
1892       {
1893         unix_ERR_class = ERRDOS;
1894         unix_ERR_code = ERRbadpath;
1895       }
1896       return(UNIXERROR(ERRDOS,ERRnoaccess));
1897     }
1898
1899   /* Realloc the parameter and data sizes */
1900   params = *pparams = Realloc(*pparams,2);
1901   if(params == NULL)
1902     return(ERROR(ERRDOS,ERRnomem));
1903
1904   SSVAL(params,0,0);
1905
1906   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1907   
1908   return(-1);
1909 }
1910
1911 /****************************************************************************
1912   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1913   We don't actually do this - we just send a null response.
1914 ****************************************************************************/
1915 static int call_trans2findnotifyfirst(connection_struct *conn,
1916                                       char *inbuf, char *outbuf, 
1917                                       int length, int bufsize,
1918                                       char **pparams, char **ppdata)
1919 {
1920   static uint16 fnf_handle = 257;
1921   char *params = *pparams;
1922   uint16 info_level = SVAL(params,4);
1923
1924   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1925
1926   switch (info_level) 
1927     {
1928     case 1:
1929     case 2:
1930       break;
1931     default:
1932       return(ERROR(ERRDOS,ERRunknownlevel));
1933     }
1934
1935   /* Realloc the parameter and data sizes */
1936   params = *pparams = Realloc(*pparams,6);
1937   if(params == NULL)
1938     return(ERROR(ERRDOS,ERRnomem));
1939
1940   SSVAL(params,0,fnf_handle);
1941   SSVAL(params,2,0); /* No changes */
1942   SSVAL(params,4,0); /* No EA errors */
1943
1944   fnf_handle++;
1945
1946   if(fnf_handle == 0)
1947     fnf_handle = 257;
1948
1949   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1950   
1951   return(-1);
1952 }
1953
1954 /****************************************************************************
1955   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
1956   changes). Currently this does nothing.
1957 ****************************************************************************/
1958 static int call_trans2findnotifynext(connection_struct *conn,
1959                                      char *inbuf, char *outbuf, 
1960                                      int length, int bufsize,
1961                                      char **pparams, char **ppdata)
1962 {
1963   char *params = *pparams;
1964
1965   DEBUG(3,("call_trans2findnotifynext\n"));
1966
1967   /* Realloc the parameter and data sizes */
1968   params = *pparams = Realloc(*pparams,4);
1969   if(params == NULL)
1970     return(ERROR(ERRDOS,ERRnomem));
1971
1972   SSVAL(params,0,0); /* No changes */
1973   SSVAL(params,2,0); /* No EA errors */
1974
1975   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1976   
1977   return(-1);
1978 }
1979
1980 /****************************************************************************
1981   reply to a SMBfindclose (stop trans2 directory search)
1982 ****************************************************************************/
1983 int reply_findclose(connection_struct *conn,
1984                     char *inbuf,char *outbuf,int length,int bufsize)
1985 {
1986         int outsize = 0;
1987         int16 dptr_num=SVALS(inbuf,smb_vwv0);
1988
1989         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
1990
1991         dptr_close(dptr_num);
1992
1993         outsize = set_message(outbuf,0,0,True);
1994
1995         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
1996
1997         return(outsize);
1998 }
1999
2000 /****************************************************************************
2001   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
2002 ****************************************************************************/
2003 int reply_findnclose(connection_struct *conn, 
2004                      char *inbuf,char *outbuf,int length,int bufsize)
2005 {
2006         int outsize = 0;
2007         int dptr_num= -1;
2008         
2009         dptr_num = SVAL(inbuf,smb_vwv0);
2010
2011         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2012
2013         /* We never give out valid handles for a 
2014            findnotifyfirst - so any dptr_num is ok here. 
2015            Just ignore it. */
2016
2017         outsize = set_message(outbuf,0,0,True);
2018
2019         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2020
2021         return(outsize);
2022 }
2023
2024 /****************************************************************************
2025  reply to a TRANS2_GET_DFS_REFERRAL
2026  ****************************************************************************/
2027 static int call_trans2getdfsreferral(connection_struct *conn,
2028                                      char *inbuf, char *outbuf, int length, 
2029                                      int bufsize, 
2030                                      char **pparams, char **ppdata,
2031                                      int total_data)
2032 {
2033         char *params = *pparams;
2034         char *pdata;
2035         char *pheader;
2036         char *localstring_offset;
2037         char *mangledstring_offset;
2038         char *sharename_offset;
2039         char *referal_offset;
2040         
2041         int i;
2042         int j;
2043         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2044         int query_file_len=0;
2045         int bytesreq=0;
2046         int filename_len;
2047         
2048         BOOL first_one=True;
2049         
2050         referal_trans_param rtp;
2051         dfs_internal_table *list=dfs_struct.table;
2052         dfs_response reply;
2053
2054         DEBUG(0,("call_trans2getdfsreferral:1\n"));
2055
2056         ZERO_STRUCT(rtp);
2057         /* decode the param member of query */
2058         rtp.level=SVAL(params, 0);
2059         DEBUGADD(0,("rtp.level:[%d]\n",rtp.level));
2060         
2061         DEBUGADD(0,("total_params:[%d]\n",total_params));
2062         for (i=0; i<(total_params-2)/2; i++)
2063         {
2064                 rtp.directory[i]=SVAL(params, 2+2*i);
2065         }
2066 /*
2067         strupper(rtp.directory);
2068 */
2069         query_file_len=strlen(rtp.directory);
2070         DEBUGADD(0,("rtp.directory:[%s]\n",rtp.directory));
2071         DEBUGADD(0,("query_file_len:[%d]\n",query_file_len));
2072                 
2073         /*
2074           lookup in the internal DFS table all the entries
2075           and calculate the required data buffer size
2076         */
2077         bytesreq=8;     /* the header */
2078         reply.number_of_referal=0;
2079         DEBUGADD(0,("call_trans2getdfsreferral:2\n"));
2080         
2081         for(i=0; i<dfs_struct.size; i++)
2082         {
2083                 filename_len=list[i].localpath_length;
2084         DEBUGADD(0,("checking against [%s][%d]\n", list[i].localpath, filename_len));
2085  
2086                 if( (filename_len==query_file_len) && 
2087                     (!strncmp(rtp.directory, list[i].localpath, query_file_len)) )
2088                 {
2089                         
2090                         bytesreq+=22;                             /* the referal size */
2091                         bytesreq+=2*(list[i].sharename_length+1); /* the string length */
2092                         reply.number_of_referal++;
2093         DEBUGADD(0,("found\n"));
2094                         
2095                         if (first_one) {
2096         DEBUGADD(0,("first one\n"));
2097                                 bytesreq+=2*(list[i].localpath_length+1);
2098                                 bytesreq+=2*(list[i].mangledpath_length+1);
2099                                 
2100                                 reply.path_consumed=list[i].localpath_length;
2101                                 
2102                                 strncpy(reply.filename, list[i].localpath, list[i].localpath_length+1);
2103                                 strncpy(reply.mangledname, list[i].mangledpath, list[i].mangledpath_length+1);
2104                                 rtp.type=list[i].type;
2105                                 first_one=False;
2106                         }
2107                 }
2108         }
2109         DEBUGADD(0,("call_trans2getdfsreferral:3\n"));
2110
2111         /* allocate memory for the reply data */        
2112         pdata = *ppdata = Realloc(*ppdata, bytesreq + 1024); 
2113         bzero(*ppdata, bytesreq+22);
2114
2115         pdata = *ppdata;
2116         pheader = pdata;
2117
2118         localstring_offset  = pdata + 8 + reply.number_of_referal*22;
2119
2120 /* unicode version */
2121         mangledstring_offset = localstring_offset + 2*(1+strlen(reply.filename));
2122         sharename_offset = mangledstring_offset + 2*(1+strlen(reply.mangledname));
2123
2124 /*ascii version 
2125         mangledstring_offset = localstring_offset + (1+strlen(reply.filename));
2126         sharename_offset = mangledstring_offset + (1+strlen(reply.mangledname));
2127 */
2128         referal_offset = pdata + 8;
2129
2130         /* right now respond storage server */
2131 /*
2132         reply.server_function=rtp.type;
2133 */
2134         reply.server_function=1;
2135
2136         /* write the header */
2137 /* unicode version*/
2138         /*SSVAL(pheader, 0, reply.path_consumed*2);*/
2139 /*ascii version 
2140
2141         SSVAL(pheader, 0, reply.path_consumed);
2142 */
2143
2144         SSVAL(pheader, 0, 6);
2145
2146         SSVAL(pheader, 2, reply.number_of_referal);
2147         SIVAL(pheader, 4, reply.server_function);
2148
2149         /* write the local path string */
2150 /* unicode version*/
2151         for(i=0; i<strlen(reply.filename); i++)
2152         {
2153                 SSVAL(localstring_offset, 2*i, (uint16) reply.filename[i]);
2154         }
2155         SSVAL(localstring_offset, 2*strlen(reply.filename), 0);
2156 /*ascii version 
2157
2158         for(i=0; i<strlen(reply.filename); i++)
2159         {
2160                 localstring_offset[i]=reply.filename[i];
2161         }
2162         localstring_offset[strlen(reply.filename)]=0;
2163 */
2164         DEBUG(0,("reply.filename is [%s]:[%d], i is [%d]\n", reply.filename, strlen(reply.filename), i));
2165
2166         /* write the mangled local path string */ 
2167 /* unicode version*/
2168         for(i=0; i<strlen(reply.mangledname); i++)
2169         {
2170                 SSVAL(mangledstring_offset, 2*i, (uint16) reply.mangledname[i]);
2171         }
2172         SSVAL(mangledstring_offset, 2*i, 0);
2173 /*ascii version 
2174
2175         for(i=0; i<strlen(reply.mangledname); i++)
2176         {
2177                 mangledstring_offset[i]=reply.mangledname[i];
2178         }
2179         mangledstring_offset[i]=0;
2180 */
2181         DEBUGADD(0,("call_trans2getdfsreferral:4\n"));
2182
2183         /* the order of the referals defines the load balancing */
2184
2185         /* write each referal */
2186         for(i=0; i<dfs_struct.size; i++)
2187         {
2188                 filename_len=list[i].localpath_length;
2189   
2190                 if(filename_len==query_file_len && 
2191                    !strncasecmp(rtp.directory, list[i].localpath, query_file_len))
2192                 {
2193                 
2194                         SSVAL(referal_offset,  0, 2);                   /* version */
2195                         SSVAL(referal_offset,  2, 22);                  /* size */
2196                         
2197                         if (rtp.type==3)
2198                                 SSVAL(referal_offset,  4, 1);           /* type SMB server*/
2199                         else            
2200                                 SSVAL(referal_offset,  4, 0);           /* type unknown */
2201                         SSVAL(referal_offset,  6, 1);                   /* flags */
2202                         SIVAL(referal_offset,  8, list[i].proximity);   /* proximity */
2203                         SIVAL(referal_offset, 12, 300);                 /* ttl */
2204                         SSVAL(referal_offset, 16, localstring_offset-referal_offset);
2205                         SSVAL(referal_offset, 18, mangledstring_offset-referal_offset);
2206                         SSVAL(referal_offset, 20, sharename_offset-referal_offset); 
2207
2208 /* unicode version      */      
2209                         for(j=0; j<list[i].sharename_length; j++)
2210                         {
2211                                 SSVAL(sharename_offset, 2*j, (uint16) list[i].sharename[j]);
2212                         }
2213                         SSVAL(sharename_offset, 2*j, 0);
2214                 
2215                         sharename_offset=sharename_offset + 2*(1+list[i].sharename_length);
2216 /*ascii version 
2217                         for(j=0; j<list[i].sharename_length; j++)
2218                         {
2219                                 sharename_offset[j]=list[i].sharename[j];
2220                         }
2221                         sharename_offset[j]=0;
2222                 
2223                         sharename_offset=sharename_offset + (1+list[i].sharename_length);
2224 */
2225
2226                         referal_offset=referal_offset+22;
2227                 }                                       
2228         }
2229         
2230         DEBUGADD(0,("call_trans2getdfsreferral:5\n"));
2231
2232         send_trans2_replies(outbuf, bufsize, params, 0, *ppdata, bytesreq+22);
2233
2234 /*      send_trans2_replies(outbuf, bufsize, *ppdata, bytesreq, params, 0);*/
2235         DEBUGADD(0,("call_trans2getdfsreferral:6\n"));
2236
2237         return(-1);
2238 }
2239                 
2240  
2241 /****************************************************************************
2242 reply to a TRANS2_REPORT_DFS_INCONSISTANCY
2243 ****************************************************************************/
2244 static int call_trans2reportdfsinconsistancy(connection_struct *conn,
2245                                              char *inbuf, char *outbuf, int length, 
2246                                              int bufsize, 
2247                                              char **pparams, char **ppdata)
2248 {
2249         char *params = *pparams;
2250
2251         DEBUG(4,("call_trans2reportdfsinconsistancy\n"));
2252         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2253         return(-1);
2254 }
2255
2256
2257 /****************************************************************************
2258   reply to a SMBtranss2 - just ignore it!
2259 ****************************************************************************/
2260 int reply_transs2(connection_struct *conn,
2261                   char *inbuf,char *outbuf,int length,int bufsize)
2262 {
2263         DEBUG(4,("Ignoring transs2 of length %d\n",length));
2264         return(-1);
2265 }
2266
2267 /****************************************************************************
2268   reply to a SMBtrans2
2269 ****************************************************************************/
2270 int reply_trans2(connection_struct *conn,
2271                  char *inbuf,char *outbuf,int length,int bufsize)
2272 {
2273         int outsize = 0;
2274         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2275         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2276 #if 0
2277         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2278         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2279         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2280         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2281         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2282         int32 timeout = IVALS(inbuf,smb_timeout);
2283 #endif
2284         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2285         unsigned int tran_call = SVAL(inbuf, smb_setup0);
2286         char *params = NULL, *data = NULL;
2287         int num_params, num_params_sofar, num_data, num_data_sofar;
2288
2289         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2290                 /* Queue this open message as we are the process of an
2291                  * oplock break.  */
2292
2293                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2294                 DEBUGADD(2,( "in oplock break state.\n"));
2295
2296                 push_oplock_pending_smb_message(inbuf, length);
2297                 return -1;
2298         }
2299         
2300         outsize = set_message(outbuf,0,0,True);
2301
2302         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2303            is so as a sanity check */
2304         if (suwcnt != 1) {
2305                 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
2306                 return(ERROR(ERRSRV,ERRerror));
2307         }
2308     
2309         /* Allocate the space for the maximum needed parameters and data */
2310         if (total_params > 0)
2311                 params = (char *)malloc(total_params);
2312         if (total_data > 0)
2313                 data = (char *)malloc(total_data);
2314   
2315         if ((total_params && !params)  || (total_data && !data)) {
2316                 DEBUG(2,("Out of memory in reply_trans2\n"));
2317         if(params)
2318           free(params);
2319         if(data)
2320           free(data); 
2321                 return(ERROR(ERRDOS,ERRnomem));
2322         }
2323
2324         /* Copy the param and data bytes sent with this request into
2325            the params buffer */
2326         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2327         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2328
2329         if (num_params > total_params || num_data > total_data)
2330                 exit_server("invalid params in reply_trans2");
2331
2332         if(params)
2333                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2334         if(data)
2335                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2336
2337         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
2338                 /* We need to send an interim response then receive the rest
2339                    of the parameter/data bytes */
2340                 outsize = set_message(outbuf,0,0,True);
2341                 send_smb(Client,outbuf);
2342
2343                 while (num_data_sofar < total_data || 
2344                        num_params_sofar < total_params) {
2345                         BOOL ret;
2346
2347                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2348                         
2349                         if ((ret && 
2350                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2351                                 outsize = set_message(outbuf,0,0,True);
2352                                 if(ret)
2353                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2354                                 else
2355                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2356                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2357                                 if(params)
2358                                         free(params);
2359                                 if(data)
2360                                         free(data);
2361                                 return(ERROR(ERRSRV,ERRerror));
2362                         }
2363       
2364                         /* Revise total_params and total_data in case
2365                            they have changed downwards */
2366                         total_params = SVAL(inbuf, smb_tpscnt);
2367                         total_data = SVAL(inbuf, smb_tdscnt);
2368                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2369                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2370                         if (num_params_sofar > total_params || num_data_sofar > total_data)
2371                                 exit_server("data overflow in trans2");
2372                         
2373                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
2374                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2375                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2376                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2377                 }
2378         }
2379         
2380         if (Protocol >= PROTOCOL_NT1) {
2381                 uint16 flg2 = SVAL(outbuf,smb_flg2);
2382                 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
2383         }
2384
2385         /* Now we must call the relevant TRANS2 function */
2386         switch(tran_call)
2387         {
2388                 case TRANSACT2_OPEN:
2389                 {
2390                         outsize = call_trans2open(conn, 
2391                                           inbuf, outbuf, bufsize, 
2392                                           &params, &data);
2393                         break;
2394                 }
2395                 case TRANSACT2_FINDFIRST:
2396                 {
2397                         outsize = call_trans2findfirst(conn, inbuf, outbuf, 
2398                                                        bufsize, &params, &data);
2399                         break;
2400                 }
2401                 case TRANSACT2_FINDNEXT:
2402                 {
2403                         outsize = call_trans2findnext(conn, inbuf, outbuf, 
2404                                                       length, bufsize, 
2405                                                       &params, &data);
2406                         break;
2407                 }
2408                 case TRANSACT2_QFSINFO:
2409                 {
2410                         outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
2411                                                  length, bufsize, &params, 
2412                                                  &data);
2413                         break;
2414                 }
2415                 case TRANSACT2_SETFSINFO:
2416                 {
2417                         outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
2418                                                        length, bufsize, 
2419                                                        &params, &data);
2420                         break;
2421                 }
2422                 case TRANSACT2_QPATHINFO:
2423                 case TRANSACT2_QFILEINFO:
2424                 {
2425                         outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
2426                                                            length, bufsize, 
2427                                                            &params, &data, total_data);
2428                         break;
2429                 }
2430                 case TRANSACT2_SETPATHINFO:
2431                 case TRANSACT2_SETFILEINFO:
2432                 {
2433                         outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
2434                                                              length, bufsize, 
2435                                                              &params, &data, 
2436                                                              total_data);
2437                         break;
2438                 }
2439                 case TRANSACT2_FINDNOTIFYFIRST:
2440                 {
2441                         outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
2442                                                              length, bufsize, 
2443                                                              &params, &data);
2444                         break;
2445                 }
2446                 case TRANSACT2_FINDNOTIFYNEXT:
2447                 {
2448                         outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
2449                                                             length, bufsize, 
2450                                                             &params, &data);
2451                         break;
2452                 }
2453                 case TRANSACT2_MKDIR:
2454                 {
2455                         outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
2456                                                    bufsize, &params, &data);
2457                         break;
2458                 }
2459                 case TRANSACT2_GET_DFS_REFERRAL:
2460                 {
2461                         outsize = call_trans2getdfsreferral(conn, inbuf, outbuf, 
2462                                                             length, bufsize, &params, 
2463                                                             &data, total_data);
2464                         break;
2465                 }
2466                 case TRANSACT2_REPORT_DFS_INCONSISTANCY:
2467                 {
2468                         outsize = call_trans2reportdfsinconsistancy(conn, inbuf, outbuf,
2469                                                                     length, bufsize, 
2470                                                                     &params, &data);
2471                         break;
2472                 }
2473                 default:
2474                 {
2475                         /* Error in request */
2476                         DEBUG(2,("Unknown request %d in trans2 call\n",
2477                                   tran_call));
2478                         if(params)
2479                                 free(params);
2480                         if(data)
2481                                 free(data);
2482                         return (ERROR(ERRSRV,ERRerror));
2483                 }
2484         }
2485         
2486         /* As we do not know how many data packets will need to be
2487            returned here the various call_trans2xxxx calls
2488            must send their own. Thus a call_trans2xxx routine only
2489            returns a value other than -1 when it wants to send
2490            an error packet. 
2491         */
2492         
2493         if(params)
2494                 free(params);
2495         if(data)
2496                 free(data);
2497         return outsize; /* If a correct response was needed the
2498                            call_trans2xxx calls have already sent
2499                            it. If outsize != -1 then it is returning */
2500 }
2501