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