home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / contrib / samba / samba-1.8 / samba-1 / samba-1.8.05 / trans2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  48.0 KB  |  1,621 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.8.
  4.    Copyright (C) Jeremy Allison 1994
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.    
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #include "includes.h"
  22. #include "loadparm.h"
  23. #include "trans2.h"
  24.  
  25. extern int DEBUGLEVEL;
  26. extern int Protocol;
  27. extern connection_struct Connections[];
  28. extern files_struct Files[];
  29. extern int num_files_open;
  30. extern BOOL casesignames;
  31.  
  32. /*********************************************************
  33. * Recursive routine that is called by lanman2_match.
  34. * Does the actual matching.
  35. *********************************************************/
  36.  
  37. static int do_match(char *str, char *regexp, int case_sig)
  38. {
  39.   char *p;
  40.  
  41.   for( p = regexp; *p && *str; ) {
  42.     switch(*p) {
  43.     case '?':
  44.       str++, p++;
  45.       break;
  46.     default:
  47.       if(case_sig) {
  48.     if(*str != *p)
  49.       return 0;
  50.       } else {
  51.     if(toupper(*str) != toupper(*p))
  52.       return 0;
  53.       }
  54.       str++, p++;
  55.       break;
  56.     case '*':
  57.       /* Look for a character matching 
  58.      the one after the '*' */
  59.       p++;
  60.       if(!*p)
  61.     return 1; /* Automatic match */
  62.       while(*str) {
  63.     while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
  64.       str++;
  65.     if(do_match(str,p,case_sig))
  66.       return 1;
  67.     if(!*str)
  68.       return 0;
  69.     else
  70.       str++;
  71.       }
  72.       return 0;
  73.     }
  74.   }
  75.   if(!*p && !*str)
  76.     return 1;
  77.   if(!*str && (*p == '*' && p[1] == '\0'))
  78.     return 1;
  79.   return 0;
  80. }
  81.  
  82. /*********************************************************
  83. * Routine to match a given string with a regexp - uses
  84. * simplified regexp that takes * and ? only. Case can be
  85. * significant or not.
  86. *********************************************************/
  87.  
  88. int lanman2_match( char *str, char *regexp, int case_sig)
  89. {
  90.   char *p;
  91.   pstring p1, p2;
  92.   int matched;
  93.  
  94.   /* Make local copies of str and regexp */
  95.   strcpy(p1,regexp);
  96.   strcpy(p2,str);
  97.  
  98.   /* Remove any *? and ** as they are meaningless */
  99.   for(p = p1; *p; p++)
  100.     while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
  101.       (void)strcpy( &p[1], &p[2]);
  102.  
  103.   DEBUG(5,("lanman2_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
  104.  
  105.   matched = do_match(p2,p1,case_sig);
  106.  
  107.   /* One final test - we need to make regexp xxx.* match all names
  108.      xxx whether they end in a '.' or not - DOS OS/2 NT
  109.      expect this. eg. *.* matches all names */
  110.  
  111.   /* Point p at the last .* in the regexp */
  112.   p = &p1[strlen(p1)-2]; 
  113.   if((!matched) && (strchr( p2, '.') == NULL) && (p >= p1) && (strcmp(p, ".*")==0)) 
  114.     {
  115.       strcat(p2, ".");
  116.       matched = do_match(p2,p1,case_sig);
  117.     }
  118.  
  119.   DEBUG(5,("lanman2_match returning %d\n", matched));
  120.  
  121.   return matched;
  122. }
  123.  
  124. /****************************************************************************
  125.   Send the required number of replies back.
  126.   We assume all fields other than the data fields are
  127.   set correctly for the type of call.
  128.   HACK ! Always assumes smb_setup field is zero.
  129. ****************************************************************************/
  130. static int send_trans2_replies(char *outbuf, int bufsize, char *params, 
  131.              int paramsize, char *pdata, int datasize)
  132. {
  133.   /* As we are using a protocol > LANMAN1 then the maxxmit
  134.      variable must have been set in the sessetupX call.
  135.      This takes precedence over the max_xmit field in the
  136.      global struct. These different max_xmit variables should
  137.      be merged as this is now too confusing */
  138.  
  139.   extern int maxxmit;
  140.   int data_to_send = datasize;
  141.   int params_to_send = paramsize;
  142.   int useable_space;
  143.   char *pp = params;
  144.   char *pd = pdata;
  145.   int params_sent_thistime, data_sent_thistime, total_sent_thistime;
  146.  
  147.   /* Initially set the wcnt area to be 10 - this is true for all
  148.      trans2 replies */
  149.   set_message(outbuf,10,0,True);
  150.  
  151.   /* If there genuinely are no parameters or data to send just send
  152.      the empty packet */
  153.   if(params_to_send == 0 && data_to_send == 0)
  154.     {
  155.       send_smb(outbuf);
  156.       return 0;
  157.     }
  158.  
  159.   /* Space is bufsize minus Netbios over TCP header minus SMB header */
  160.   useable_space = bufsize - (smb_buf(outbuf) - outbuf);
  161.   useable_space = MIN(useable_space, maxxmit);
  162.  
  163.   while( params_to_send || data_to_send)
  164.     {
  165.       /* Calculate whether we will totally or partially fill this packet */
  166.       total_sent_thistime = params_to_send + data_to_send;
  167.       total_sent_thistime = MIN(total_sent_thistime, useable_space);
  168.  
  169.       set_message(outbuf, 10, total_sent_thistime, True);
  170.  
  171.       /* Set total params and data to be sent */
  172.       SSVAL(outbuf,smb_tprcnt,paramsize);
  173.       SSVAL(outbuf,smb_tdrcnt,datasize);
  174.  
  175.       /* Calculate how many parameters and data we can fit into
  176.      this packet. Parameters get precedence */
  177.  
  178.       params_sent_thistime = MIN(params_to_send,useable_space);
  179.       data_sent_thistime = useable_space - params_sent_thistime;
  180.       data_sent_thistime = MIN(data_sent_thistime,data_to_send);
  181.  
  182.       SSVAL(outbuf,smb_prcnt, params_sent_thistime);
  183.       if(params_sent_thistime == 0)
  184.     {
  185.       SSVAL(outbuf,smb_proff,0);
  186.       SSVAL(outbuf,smb_prdisp,0);
  187.     } else {
  188.       /* smb_proff is the offset from the start of the SMB header to the
  189.          parameter bytes, however the first 4 bytes of outbuf are
  190.          the Netbios over TCP header. Thus use smb_base() to subtract
  191.          them from the calculation */
  192.       SSVAL(outbuf,smb_proff,(smb_buf(outbuf) - smb_base(outbuf)));
  193.       /* Absolute displacement of param bytes sent in this packet */
  194.       SSVAL(outbuf,smb_prdisp,pp - params);
  195.     }
  196.  
  197.       SSVAL(outbuf,smb_drcnt, data_sent_thistime);
  198.       if(data_sent_thistime == 0)
  199.     {
  200.       SSVAL(outbuf,smb_droff,0);
  201.       SSVAL(outbuf,smb_drdisp, 0);
  202.     } else {
  203.       /* The offset of the data bytes is the offset of the
  204.          parameter bytes plus the number of parameters being sent this time */
  205.       SSVAL(outbuf,smb_droff,(smb_buf(outbuf) - smb_base(outbuf)) + params_sent_thistime);
  206.       SSVAL(outbuf,smb_drdisp, pd - pdata);
  207.     }
  208.  
  209.       /* Copy the param bytes into the packet */
  210.       if(params_sent_thistime)
  211.     memcpy(smb_buf(outbuf),pp,params_sent_thistime);
  212.       /* Copy in the data bytes */
  213.       if(data_sent_thistime)
  214.     memcpy(smb_buf(outbuf)+params_sent_thistime,pd,data_sent_thistime);
  215.  
  216.       DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
  217.            params_sent_thistime, data_sent_thistime, useable_space));
  218.       DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
  219.            params_to_send, data_to_send, paramsize, datasize));
  220.  
  221.       /* Send the packet */
  222.       send_smb(outbuf);
  223.  
  224.       pp += params_sent_thistime;
  225.       pd += data_sent_thistime;
  226.  
  227.       params_to_send -= params_sent_thistime;
  228.       data_to_send -= data_sent_thistime;
  229.  
  230.       /* Sanity check */
  231.       if(params_to_send < 0 || data_to_send < 0)
  232.     {
  233.       DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
  234.            params_to_send, data_to_send));
  235.       return -1;
  236.     }
  237.     }
  238.  
  239.   return 0;
  240. }
  241.  
  242.  
  243. /****************************************************************************
  244.   reply to a TRANSACT2_OPEN
  245. ****************************************************************************/
  246.  
  247. int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, 
  248.             char **pparams, char **ppdata)
  249. {
  250.   char *params = *pparams;
  251.   int16 open_mode = SVAL(params, 2);
  252.   int16 open_attr = SVAL(params,6);
  253. #if 0
  254.   BOOL return_additional_info = BITSETW(params,0);
  255.   int16 open_sattr = SVAL(params, 4);
  256.   int32 open_time = IVAL(params,8);
  257. #endif
  258.   int16 open_ofun = SVAL(params,12);
  259.   int32 open_size = IVAL(params,14);
  260.   int16 name_len = SVAL(params,22);
  261.   char *pname = ¶ms[24];
  262.   pstring fname = "";
  263.   int fnum = -1;
  264.   int openmode = 0;
  265.   BOOL file_existed = False;
  266.   int unixmode;
  267.   int size=0,fmode=0,mtime=0,rmode;
  268.   int32 inode = 0;
  269.   struct stat sbuf;
  270.  
  271.   StrnCpy(fname,pname,name_len);
  272.  
  273.   DEBUG(3,("call_trans2open %s cnum = %d open_mode=%d open_attr = %d open_ofun = %d open_size = %d\n",
  274.      fname,cnum,open_mode, open_attr, open_ofun, open_size));
  275.  
  276.   /* XXXX we need to handle passed times, sattr and flags */
  277.  
  278.   unix_convert(fname,cnum);
  279.   
  280.   rmode = open_mode & 0x7;
  281.  
  282.   switch (open_mode & 0x7)
  283.     {
  284.     case 0:       
  285.       openmode = O_RDONLY; 
  286.       break;
  287.     case 1: 
  288.       openmode = O_WRONLY; 
  289.       break;
  290.     case 0x7: 
  291.     case 2: 
  292.       rmode = 2;
  293.       openmode = O_RDWR; 
  294.       break;
  295.     case 3:  /* map execute to read */
  296.       openmode = O_RDONLY; 
  297.       break;
  298.     default:
  299.       rmode = 0;
  300.       openmode = O_RDONLY;
  301.       break;
  302.     }
  303.   
  304.   /* now add create and trunc bits */
  305.   if (open_ofun & 0x10)
  306.     openmode |= O_CREAT;
  307.   if ((open_ofun & 0x3) == 2)
  308.     openmode |= O_TRUNC;
  309.   
  310.   fnum = find_free_file();
  311.   if (fnum < 0)
  312.     return(ERROR(ERRSRV,ERRnofids));
  313.  
  314.   if (!check_name(fname,cnum))
  315.     return(ERROR(ERRDOS,ERRnoaccess));
  316.  
  317.   unixmode = unix_mode(cnum,open_attr);
  318.       
  319.   file_existed = file_exist(fname);
  320.       
  321.   if ((open_ofun & 0x3) == 0 && file_existed)
  322.     return(ERROR(ERRDOS,ERRbadfile));
  323.       
  324.   open_file(fnum,cnum,fname,openmode,unixmode);
  325.       
  326.   if (!Files[fnum].open)
  327.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  328.  
  329.   if (fstat(Files[fnum].fd,&sbuf) != 0)
  330.     {
  331.       close_file(fnum);
  332.       return(ERROR(ERRDOS,ERRnoaccess));
  333.     }
  334.     
  335.   size = sbuf.st_size;
  336.   fmode = dos_mode(cnum,fname,&sbuf);
  337.   mtime = sbuf.st_mtime;
  338.   inode = sbuf.st_ino;
  339.   if (fmode & aDIR)
  340.     {
  341.       close_file(fnum);
  342.       return(ERROR(ERRDOS,ERRnoaccess));
  343.     }
  344.  
  345.   /* Realloc the size of parameters and data we will return */
  346.   params = *pparams = Realloc(*pparams, 28);
  347.   if(params == NULL)
  348.     return(ERROR(ERRDOS,ERRnomem));
  349.  
  350.   memset(params,'\0',28);
  351.   SSVAL(params,0,fnum);
  352.   SSVAL(params,2,fmode);
  353.   put_dos_date2(params,4, mtime);
  354.   SIVAL(params,8, size);
  355.   SSVAL(params,12,rmode);
  356.   {
  357.     int smb_action = 0;
  358.     
  359.     if (file_existed && !(openmode & O_TRUNC)) smb_action = 1;
  360.     if (!file_existed) smb_action = 2;
  361.     if (file_existed && (openmode & O_TRUNC)) smb_action = 3;
  362.  
  363.     /* if they requested a opportunistic lock and they have it read-only
  364.        then tell them they have it - this is wrong but it might work */
  365.     if ((CVAL(inbuf,smb_flg) & 0x20) && openmode == O_RDONLY)
  366.       smb_action |= 0x8000;
  367.     
  368.     SSVAL(params,18,smb_action);
  369.   }
  370.   SIVAL(params,20,inode);
  371.  
  372.   DEBUG(3,("%s TRANS2_OPEN %s fd=%d fnum=%d cnum=%d mode=%d omode=%d (numopen=%d)\n",
  373.      timestring(),fname,Files[fnum].fd,fnum,cnum,
  374.      open_mode,openmode,num_files_open));
  375.  
  376.   /* Send the required number of replies */
  377.   send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
  378.  
  379.   return -1;
  380. }
  381.  
  382. /****************************************************************************
  383.   get a level dependent lanman2 dir entry.
  384. ****************************************************************************/
  385. static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level,
  386.                  int requires_resume_key,
  387.                  BOOL dont_descend,char **ppdata, 
  388.                  char *base_data, int space_remaining, 
  389.                  BOOL *out_of_space,
  390.                  int *last_name_off)
  391. {
  392.   struct DIRECT *dptr;
  393.   BOOL found = False;
  394.   struct stat sbuf;
  395.   pstring mask;
  396.   pstring pathreal;
  397.   pstring fname= "";
  398.   BOOL matched;
  399.   char *p, *pdata = *ppdata;
  400.   int reskey, prev_dirpos;
  401.   int mode=0;
  402.   uint32 size=0;
  403.   uint32 mdate=0, adate=0, cdate=0;
  404.   int name_offset;
  405.   int space_for_this_entry;
  406.  
  407.   *out_of_space = False;
  408.  
  409.   if (!Connections[cnum].dirptr)
  410.     return(False);
  411.  
  412.   p = strrchr(path_mask,'/');
  413.   if(p != NULL)
  414.     {
  415.       if(p[1] == '\0')
  416.     strcpy(mask,"*.*");
  417.       else
  418.     strcpy(mask, p+1);
  419.     }
  420.   else
  421.     strcpy(mask, path_mask);
  422.  
  423.   while (!found)
  424.     {
  425.       /* Needed if we run out of space */
  426.       prev_dirpos = telldir(Connections[cnum].dirptr);
  427.       dptr = readdir(Connections[cnum].dirptr);
  428.  
  429.       reskey = telldir(Connections[cnum].dirptr);
  430.  
  431.       DEBUG(3,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
  432.            Connections[cnum].dirptr,telldir(Connections[cnum].dirptr)));
  433.       
  434.       if (dptr == NULL) 
  435.     return(False);
  436.       
  437.      
  438. #ifdef NEXT2
  439.       DEBUG(3,("get_lanman2_dir_entry:name is: %s\n", dptr->d_name));
  440.       if (telldir(Connections[cnum].dirptr)<0) {
  441.         DEBUG(3,("get_lanman2_dir_entry encountered null - returning false.\n"));
  442.         return(False);
  443.       }
  444. #endif
  445.  
  446.       matched = False;
  447.  
  448.       strcpy(fname,dptr->d_name);      
  449.  
  450.       if(lanman2_match(fname, mask, casesignames))
  451.     {
  452.       if (dont_descend &&
  453.           !strequal(fname,".") && !strequal(fname,".."))
  454.         continue;
  455.  
  456.       strcpy(pathreal,Connections[cnum].dirpath);
  457.       strcat(pathreal,"/");
  458.       strcat(pathreal,fname);
  459.       if (stat(pathreal,&sbuf) != 0) 
  460.         {
  461.           DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
  462.           continue;
  463.         }
  464.  
  465.       /* Work out if we have enough space to include
  466.          this entry */
  467.       space_for_this_entry = strlen(fname) + 1;
  468.       space_for_this_entry += (requires_resume_key ? 4 : 0);
  469.       space_for_this_entry += ((info_level == 1) ? l1_achName : l2_achName);
  470.       if(space_for_this_entry > space_remaining)
  471.         {
  472.           /* Move the dirptr back to prev_dirpos */
  473.           seekdir(Connections[cnum].dirptr, prev_dirpos);
  474.           *out_of_space = True;
  475.           DEBUG(9,("get_lanman2_dir_entry: space_for_this_entry = %d, space_remaining = %d\n",
  476.             space_for_this_entry, space_remaining));
  477.           return False; /* Not finished - just out of space */
  478.         }
  479.  
  480.       mode = dos_mode(cnum,pathreal,&sbuf);
  481.  
  482.       if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
  483.         {          
  484.           DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
  485.           continue;
  486.         }
  487.       size = sbuf.st_size;
  488.       mdate = sbuf.st_mtime;
  489.       adate = sbuf.st_atime;
  490.       cdate = sbuf.st_ctime;
  491.       if(mode & aDIR)
  492.         size = 0;
  493.  
  494.       DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
  495.       
  496.       found = True;
  497.     }
  498.     }
  499.  
  500.   /* Set up the level 1 or level 2 data block */
  501.   if(requires_resume_key)
  502.     {
  503.       SIVAL(pdata,0,reskey);
  504.       pdata += 4;
  505.     }
  506.  
  507.   if(info_level == 1)
  508.     {
  509.       put_dos_date2(pdata,l1_fdateCreation,cdate);
  510.       put_dos_date2(pdata,l1_fdateLastAccess,adate);
  511.       put_dos_date2(pdata,l1_fdateLastWrite,mdate);
  512.       SIVAL(pdata,l1_cbFile,size);
  513.       SIVAL(pdata,l1_cbFileAlloc,1024); /* Make 1024 for now */
  514.       SSVAL(pdata,l1_attrFile,mode);
  515.       SCVAL(pdata,l1_cchName,strlen(fname));
  516.       strcpy(pdata + l1_achName, fname);
  517.       name_offset = l1_achName;
  518.     }
  519.   else 
  520.     { /* info_level 2 */
  521.       put_dos_date2(pdata,l2_fdateCreation,cdate);
  522.       put_dos_date2(pdata,l2_fdateLastAccess,adate);
  523.       put_dos_date2(pdata,l2_fdateLastWrite,mdate);
  524.       SIVAL(pdata,l2_cbFile,size);
  525.       SIVAL(pdata,l2_cbFileAlloc,1024); /* Make 1024 for now */
  526.       SSVAL(pdata,l2_attrFile,mode);
  527.       SIVAL(pdata,l2_cbList,0); /* No extended attributes */
  528.       SCVAL(pdata,l2_cchName,strlen(fname));
  529.       strcpy(pdata + l2_achName, fname);
  530.       name_offset = l2_achName;
  531.     }
  532.   /* Setup the last_filename pointer, as an offset from base_data */
  533.   *last_name_off = (pdata - base_data) + name_offset;
  534.   /* Advance the data pointer to the next slot */
  535.   *ppdata = pdata + name_offset + strlen(pdata + name_offset) + 1;
  536.   return(found);
  537. }
  538.   
  539. /****************************************************************************
  540.   returns maximum size of buffer needed to return a FINDFIRST/NEXT entry
  541. ****************************************************************************/
  542. int level_info_size(int level, BOOL requires_resume_key)
  543. {
  544.   int size = ( level == 1 ? l1_achName : l2_achName);
  545.   
  546.   size += sizeof(pstring);
  547.   size += ( requires_resume_key ? 4 : 0);
  548.   return size;
  549. }
  550.  
  551. /****************************************************************************
  552.   checks info level for validity.
  553. ****************************************************************************/
  554. int check_info_level(char *inbuf, char *outbuf, int info_level)
  555. {
  556.   /* We only support info levels 1 and 2 */
  557.   if(info_level == 3)
  558.     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
  559.  
  560.   if(info_level != 1 && info_level != 2)
  561.     return(ERROR(ERRSRV,ERRnosupport));
  562.  
  563.   return 0;
  564. }
  565.  
  566. /****************************************************************************
  567.   reply to a TRANS2_FINDFIRST
  568. ****************************************************************************/
  569. int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum, 
  570.              char **pparams, char **ppdata)
  571. {
  572.   /* We must be careful here that we don't return more than the
  573.      allowed number of data bytes. If this means returning fewer than
  574.      maxentries then so be it. We assume that the redirector has
  575.      enough room for the fixed number of parameter bytes it has
  576.      requested. */
  577.   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
  578.   char *params = *pparams;
  579.   char *pdata = *ppdata;
  580.   int dirtype = SVAL(params,0);
  581.   int maxentries = SVAL(params,2);
  582.   BOOL close_after_first = BITSETW(params+4,0);
  583.   BOOL close_if_end = BITSETW(params+4,1);
  584.   BOOL requires_resume_key = BITSETW(params+4,2);
  585.   int info_level = SVAL(params,6);
  586.   pstring directory = "";
  587.   pstring mask = "";
  588.   char *p, *wcard;
  589.   int last_name_off;
  590.   int dptr_num = -1;
  591.   int return_data_size;
  592.   int numentries = 0;
  593.   int i, outsize;
  594.   BOOL finished = False;
  595.   BOOL dont_descend = False;
  596.   BOOL out_of_space = False;
  597.   int space_remaining;
  598.  
  599.   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",
  600.        dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
  601.        info_level, max_data_bytes));
  602.  
  603.   if((outsize = check_info_level(inbuf, outbuf, /* Needed for error return */ info_level)))
  604.     return outsize;
  605.  
  606.   strcpy(directory, params + 12); /* Complete directory path with wildcard mask appended */
  607.  
  608.   DEBUG(5,("path=%s\n",directory));
  609.  
  610.   unix_convert(directory,cnum);
  611.   if(!check_name(directory,cnum)) {
  612.     return(ERROR(ERRDOS,ERRbadpath));
  613.   }
  614.   p = strrchr(directory,'/');
  615.   if(p == NULL) {
  616.     strcpy(mask,directory);
  617.     strcpy(directory,"./");
  618.   } else {
  619.     strcpy(mask,p+1);
  620.     *p = 0;
  621.   }
  622.  
  623.   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
  624.  
  625.   /* Realloc the data to point to the required buffer size */
  626.   if((return_data_size = level_info_size(info_level, requires_resume_key))!=-1)
  627.     {
  628.       return_data_size *= maxentries;
  629.       if(return_data_size > max_data_bytes)
  630.     return_data_size = max_data_bytes;
  631.       *ppdata = Realloc( *ppdata, return_data_size );
  632.       if(*ppdata == NULL)
  633.     return(ERROR(ERRDOS,ERRnomem));
  634.       pdata = *ppdata;
  635.     }
  636.   else
  637.     return(ERROR(ERRSRV,ERRerror));
  638.  
  639.   /* Realloc the params space */
  640.   params = *pparams = Realloc(*pparams, 10);
  641.   if(params == NULL)
  642.     return(ERROR(ERRDOS,ERRnomem));
  643.  
  644.   if(!start_dir(cnum,directory))
  645.     return(ERROR(ERRDOS,ERRbadpath));
  646.     
  647.   dptr_num = dptr_create(Connections[cnum].dirptr,directory, True ,SVAL(inbuf,smb_pid));
  648.   if (dptr_num < 0)
  649.     {
  650.       if(Connections[cnum].dirptr != NULL)
  651.     closedir(Connections[cnum].dirptr);
  652.       return(ERROR(ERRDOS,ERRnofids));
  653.     }
  654.  
  655.   /* Save the wildcard match and attribs we are using on this directory - needed as
  656.      lanman2 assumes these are being saved between calls */
  657.  
  658.   if(!(wcard = strdup(mask)))
  659.     {
  660.       dptr_demote(dptr_num);
  661.       dptr_close(dptr_num);
  662.       return(ERROR(ERRDOS,ERRnomem));
  663.     }
  664.  
  665.   dptr_set_wcard(dptr_num, wcard);
  666.   dptr_set_attr(dptr_num, dirtype);
  667.  
  668.   DEBUG(3,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
  669.  
  670.   /* We don't need to check for VOL here as this is returned by 
  671.      a different TRANS2 call. */
  672.  
  673.   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
  674.   if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),casesignames))
  675.     dont_descend = True;
  676.     
  677.   p = pdata;
  678.   space_remaining = max_data_bytes;
  679.   out_of_space = False;
  680.  
  681.   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
  682.     {
  683.  
  684.       finished = 
  685.     !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
  686.                    requires_resume_key,dont_descend,
  687.                    &p,pdata,space_remaining, &out_of_space,
  688.                    &last_name_off);
  689.       if (!finished && !out_of_space)
  690.     numentries++;
  691.       space_remaining = max_data_bytes - (p - pdata);
  692.     }
  693.   
  694.   /* Check if we can close the dirptr */
  695.   if(close_after_first || (finished && close_if_end))
  696.     {
  697.       dptr_demote(dptr_num);
  698.       dptr_close(dptr_num);
  699.       DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
  700.       dptr_num = -1;
  701.     }
  702.  
  703.   if(finished && (numentries == 0))
  704.     {
  705.       return(ERROR(ERRDOS,ERRnofiles));
  706.     }
  707.  
  708.   /* At this point pdata points to numentries directory entries. */
  709.  
  710.   /* Set up the return parameter block */
  711.   SSVAL(params,0,dptr_num);
  712.   SSVAL(params,2,numentries);
  713.   SSVAL(params,4,finished);
  714.   SSVAL(params,6,0); /* Never an EA error */
  715.   SSVAL(params,8,last_name_off);
  716.  
  717.   send_trans2_replies( outbuf, bufsize, params, 10, pdata, p - pdata);
  718.  
  719.   if ((! *directory) && dptr_path(dptr_num))
  720.     sprintf(directory,"(%s)",dptr_path(dptr_num));
  721.  
  722.   DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
  723.     timestring(),
  724.     smb_fn_name(CVAL(inbuf,smb_com)), 
  725.     mask,directory,cnum,dirtype,numentries));
  726.  
  727.   return(-1);
  728. }
  729.  
  730. /****************************************************************************
  731.   reply to a TRANS2_FINDNEXT
  732. ****************************************************************************/
  733.  
  734. int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize,
  735.             int cnum, char **pparams, char **ppdata)
  736. {
  737.   /* We must be careful here that we don't return more than the
  738.      allowed number of data bytes. If this means returning fewer than
  739.      maxentries then so be it. We assume that the redirector has
  740.      enough room for the fixed number of parameter bytes it has
  741.      requested. */
  742.   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
  743.   char *params = *pparams;
  744.   char *pdata = *ppdata;
  745.   int16 dptr_num = SVAL(params,0);
  746.   uint16 maxentries = SVAL(params,2);
  747.   uint16 info_level = SVAL(params,4);
  748.   uint32 resume_key = IVAL(params,6);
  749.   BOOL close_after_request = BITSETW(params+10,0);
  750.   BOOL close_if_end = BITSETW(params+10,1);
  751.   BOOL requires_resume_key = BITSETW(params+10,2);
  752.   pstring mask = "";
  753.   pstring directory = "";
  754.   char *p;
  755.   uint16 dirtype;
  756.   int return_data_size;
  757.   int numentries = 0;
  758.   int i, last_name_off, outsize;
  759.   BOOL finished = False;
  760.   BOOL dont_descend = False;
  761.   BOOL out_of_space = False;
  762.   int space_remaining;
  763.  
  764.   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, close_after_request=%d, close_if_end = %d requires_resume_key = %d resume_key = %d level = %d\n",
  765.        dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
  766.        requires_resume_key, info_level));
  767.  
  768.   if((outsize = check_info_level(inbuf, outbuf, /* Needed for error return */ info_level)))
  769.     return outsize;
  770.  
  771.   /* Realloc the data to point to the required buffer size */
  772.   if((return_data_size = level_info_size(info_level, requires_resume_key))!=-1)
  773.     {
  774.       return_data_size *= maxentries;
  775.       if(return_data_size > max_data_bytes)
  776.     return_data_size = max_data_bytes;
  777.       *ppdata = Realloc( *ppdata, return_data_size );
  778.  
  779.       if(*ppdata == NULL)
  780.     return(ERROR(ERRDOS,ERRnomem));
  781.       pdata = *ppdata;
  782.     }
  783.   else
  784.     return(ERROR(ERRSRV,ERRerror));
  785.  
  786.   /* Realloc the params space */
  787.   params = *pparams = Realloc(*pparams, 6*sizeof(WORD));
  788.   if(params == NULL)
  789.     return(ERROR(ERRDOS,ERRnomem));
  790.  
  791.   /* Check that the dptr is valid */
  792.  
  793.   if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
  794.     return(ERROR(ERRDOS,ERRnofiles));
  795.  
  796.   StrnCpy(Connections[cnum].dirpath,dptr_path(dptr_num),sizeof(pstring)-1);
  797.  
  798.   /* Get the wildcard mask from the dptr */
  799.   if((p = dptr_wcard(dptr_num))== NULL)
  800.     {
  801.       DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
  802.       return (ERROR(ERRDOS,ERRnofiles));
  803.     }
  804.   strcpy(mask, p);
  805.   strcpy(directory,Connections[cnum].dirpath);
  806.  
  807.   /* Get the attr mask from the dptr */
  808.   dirtype = dptr_attr(dptr_num);
  809.  
  810.   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x",dptr_num, mask, dirtype));
  811.  
  812.   /* We don't need to check for VOL here as this is returned by 
  813.      a different TRANS2 call. */
  814.  
  815.   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
  816.   if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),casesignames))
  817.     dont_descend = True;
  818.     
  819.   p = pdata;
  820.   space_remaining = max_data_bytes;
  821.   out_of_space = False;
  822.  
  823.   /* If we have a resume key - seek to the correct position. */
  824.   if(requires_resume_key)
  825.     seekdir( Connections[cnum].dirptr, resume_key);
  826.  
  827.   for (i=0;(i<maxentries) && !finished && !out_of_space ;i++)
  828.     {
  829.       finished = 
  830.     !get_lanman2_dir_entry(cnum,mask,dirtype,info_level,
  831.                    requires_resume_key,dont_descend,
  832.                    &p,pdata,space_remaining, &out_of_space,
  833.                    &last_name_off);
  834.       if (!finished && !out_of_space)
  835.     numentries++;
  836.       space_remaining = max_data_bytes - (p - pdata);
  837.     }
  838.   
  839.   /* Check if we can close the dirptr */
  840.   if(close_after_request || (finished && close_if_end))
  841.     {
  842.       dptr_demote(dptr_num);
  843.       dptr_close(dptr_num); /* This frees up the saved mask */
  844.       DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
  845.       dptr_num = -1;
  846.     }
  847.  
  848.   /* At this point pdata points to numentries directory entries. */
  849.   if(finished && (numentries == 0))
  850.     {
  851.       return(ERROR(ERRDOS,ERRnofiles));
  852.     }
  853.  
  854.   /* Set up the return parameter block */
  855.   SSVAL(params,0,numentries);
  856.   SSVAL(params,2,finished);
  857.   SSVAL(params,4,0); /* Never an EA error */
  858.   SSVAL(params,6,last_name_off);
  859.  
  860.   send_trans2_replies( outbuf, bufsize, params, 12, pdata, p - pdata);
  861.  
  862.   if ((! *directory) && dptr_path(dptr_num))
  863.     sprintf(directory,"(%s)",dptr_path(dptr_num));
  864.  
  865.   DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
  866.     timestring(),
  867.     smb_fn_name(CVAL(inbuf,smb_com)), 
  868.     mask,directory,cnum,dirtype,numentries));
  869.  
  870.   return(-1);
  871. }
  872.  
  873. /****************************************************************************
  874.   reply to a TRANS2_QFSINFO (query filesystem info)
  875. ****************************************************************************/
  876.  
  877. int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
  878.             int cnum, char **pparams, char **ppdata)
  879. {
  880.   char *pdata = *ppdata;
  881.   char *params = *pparams;
  882.   uint16 info_level = SVAL(params,0);
  883.   int outsize = 0;
  884.   pstring service_name = "";
  885.   int data_len;
  886.   struct stat st;
  887.       
  888.   DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level));
  889.  
  890.   if((outsize = check_info_level(inbuf, outbuf, /* Needed for error return */ info_level)))
  891.     return outsize;
  892.  
  893.   /* Realloc the data space (big enough for level 1 and level 2 answers). */
  894.   pdata = *ppdata = Realloc(*ppdata, 9*sizeof(WORD));
  895.   if(pdata == NULL)
  896.     return(ERROR(ERRDOS,ERRnomem));
  897.  
  898.   strcpy(service_name,SERVICE(SNUM(cnum)));
  899.  
  900.   if(stat(".",&st)!=0)
  901.     {
  902.       DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
  903.       return (ERROR(ERRSRV,ERRinvdevice));
  904.     }
  905.  
  906.   if(info_level == 1)
  907.     {
  908.       int dfree,dsize,bsize;
  909.  
  910.       disk_free(".",&bsize,&dfree,&dsize);
  911.  
  912.       SIVAL(pdata,l1_idFileSystem,st.st_dev);
  913.       SIVAL(pdata,l1_cSectorUnit,bsize/512);
  914.       SIVAL(pdata,l1_cUnit,dsize);
  915.       SIVAL(pdata,l1_cUnitAvail,dfree);
  916.       SSVAL(pdata,l1_cbSector,512);
  917.       data_len = 18;
  918.       DEBUG(5,("call_trans2qfsinfo : bsize = %d, idFileSystem = %x, cSectorUnit = %d, cUnit = %d, cUnitAvail = %d, cbSector = %d\n", bsize, st.st_dev, bsize/512, dsize, dfree, 512));
  919.     }
  920.   else
  921.     { 
  922.       /* Return volume name */
  923.       int volname_len = strlen(service_name);
  924.       if(volname_len > 11)
  925.     volname_len = 11;
  926.  
  927.       put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
  928.       SCVAL(pdata,l2_vol_cch,volname_len);
  929.       StrnCpy(pdata+l2_vol_szVolLabel,service_name,volname_len);
  930.       *(pdata+l2_vol_szVolLabel+volname_len) = '\0';
  931.       data_len = l2_vol_szVolLabel + volname_len + 1;
  932.       DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime,volname_len,
  933.            pdata+l2_vol_szVolLabel));
  934.     }
  935.  
  936.   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
  937.  
  938.   DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level));
  939.  
  940.   return -1;
  941. }
  942.  
  943. /****************************************************************************
  944.   reply to a TRANS2_SETFSINFO (set filesystem info)
  945. ****************************************************************************/
  946.  
  947. int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize,
  948.             int cnum, char **pparams, char **ppdata)
  949. {
  950.   /* Just say yes we did it - there is nothing that
  951.      can be set here so it doesn't matter. */
  952.   int outsize;
  953.   DEBUG(3,("call_trans2setfsinfo\n"));
  954.  
  955.   if (!CAN_WRITE(cnum))
  956.     return(ERROR(ERRSRV,ERRaccess));
  957.  
  958.   outsize = set_message(outbuf,10,0,True);
  959.  
  960.   return outsize;
  961. }
  962.  
  963. /****************************************************************************
  964.   reply to a TRANS2_QPATHINFO (query file info by path)
  965. ****************************************************************************/
  966.  
  967. int call_trans2qpathinfo(char *inbuf, char *outbuf, int length, int bufsize,
  968.             int cnum, char **pparams, char **ppdata)
  969. {
  970.   char *params = *pparams;
  971.   char *pdata = *ppdata;
  972.   uint16 info_level = SVAL(params,0);
  973.   int mode;
  974.   int size;
  975.   pstring fname;
  976.   unsigned int data_size;
  977.   int outsize;
  978.   struct stat sbuf;
  979.   BOOL ok = False;
  980.  
  981.   DEBUG(3,("call_trans2qpathinfo info_level = %d\n", info_level));
  982.  
  983.   if((outsize = check_info_level(inbuf, outbuf, /* Needed for error return */ info_level)))
  984.     return outsize;
  985.  
  986.   strcpy(fname,¶ms[6]);
  987.  
  988.   unix_convert(fname,cnum);
  989.   if (check_name(fname,cnum))
  990.     {
  991.       if (stat(fname,&sbuf) == 0)
  992.     {
  993.       mode = dos_mode(cnum,fname,&sbuf);
  994.       size = sbuf.st_size;
  995.       if (mode & aDIR)
  996.         size = 0;
  997.       ok = True;
  998.     }
  999.       else
  1000.     DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
  1001.     }
  1002.   
  1003.   if (!ok)
  1004.     return(UNIXERROR(ERRDOS,ERRbadfile));
  1005.   
  1006.   /* Realloc the parameter and data sizes */
  1007.   params = *pparams = Realloc(*pparams,2);
  1008.   if(params == NULL)
  1009.     return(ERROR(ERRDOS,ERRnomem));
  1010.  
  1011.   data_size = (info_level == 1 ? 22 : 26);
  1012.  
  1013.   if(data_size > SVAL(inbuf, smb_mdrcnt))
  1014.     {
  1015.       DEBUG(3,("trans2qpathinfo : max_data = %d, data_size = %d\n",
  1016.         SVAL(inbuf,smb_mdrcnt), data_size));
  1017.     }
  1018.   pdata = *ppdata = Realloc(*ppdata, data_size);
  1019.   if(pdata == NULL)
  1020.     return(ERROR(ERRDOS,ERRnomem));
  1021.  
  1022.   /* No extended attribute errors */
  1023.   SSVAL(params,0,0);
  1024.  
  1025.   put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime);
  1026.   put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
  1027.   put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime);
  1028.   SIVAL(pdata,l1_cbFile,size);
  1029.   SIVAL(pdata,l1_cbFileAlloc,1024); /* Make 1024 for now */
  1030.   SSVAL(pdata,l1_attrFile,mode);
  1031.   if(info_level == 2)
  1032.     SIVAL(pdata,l2_cbList,0);
  1033.  
  1034.   send_trans2_replies( outbuf, bufsize, params, 2, pdata, data_size);
  1035.  
  1036.   DEBUG(3,("%s trans2qpathinfo name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
  1037.   
  1038.   return(-1);
  1039. }
  1040.  
  1041. /****************************************************************************
  1042.   reply to a TRANS2_SETPATHINFO (set file info by path)
  1043. ****************************************************************************/
  1044.  
  1045. int call_trans2setpathinfo(char *inbuf, char *outbuf, int length, int bufsize,
  1046.             int cnum, char **pparams, char **ppdata)
  1047. {
  1048.   char *params = *pparams;
  1049.   char *pdata = *ppdata;
  1050.   uint16 info_level = SVAL(params,0);
  1051.   int mode=0;
  1052.   int size=0;
  1053.   struct utimbuf tvs;
  1054.   int fd;
  1055.   int outsize;
  1056.   BOOL is_directory = False;
  1057.   struct stat st;
  1058.   pstring fname;
  1059.  
  1060.   DEBUG(3,("call_trans2setpathinfo info_level = %d\n", info_level));
  1061.  
  1062.   if((outsize = check_info_level(inbuf, outbuf, /* Needed for error return */ info_level)))
  1063.     return outsize;
  1064.  
  1065.   /* extract the filename */
  1066.   strcpy(fname,¶ms[6]);
  1067.  
  1068.   /* Realloc the parameter and data sizes */
  1069.   params = *pparams = Realloc(*pparams,2);
  1070.   if(params == NULL)
  1071.     return(ERROR(ERRDOS,ERRnomem));
  1072.  
  1073.   unix_convert(fname,cnum);
  1074.   if(!check_name(fname, cnum))
  1075.     return(ERROR(ERRDOS,ERRbadpath));
  1076.  
  1077.   if (!CAN_WRITE(cnum))
  1078.     return(ERROR(ERRSRV,ERRaccess));
  1079.  
  1080.   if(stat(fname,&st)!=0)
  1081.     {
  1082.       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
  1083.       return(ERROR(ERRDOS,ERRbadpath));
  1084.     }
  1085.  
  1086.   is_directory = ( st.st_mode & S_IFDIR ) ? True : False;
  1087.  
  1088.   tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
  1089.   tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
  1090.   mode = unix_mode(cnum,SVAL(pdata,l1_attrFile));
  1091.   size = IVAL(pdata,l1_cbFile);
  1092.  
  1093.   /* Try and set the times, size and mode of this file - if they are different 
  1094.    from the current values */
  1095.   if(!is_directory && (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime))
  1096.     {
  1097.       if(utime(fname, &tvs)!=0)
  1098.     {
  1099.       DEBUG(3,("utime of %s failed (%s)\n", fname, strerror(errno)));
  1100.       if(errno == ENOENT)
  1101.         return(ERROR(ERRDOS,ERRbadpath));
  1102.       return(ERROR(ERRDOS,ERRnoaccess));
  1103.     }
  1104.     }
  1105.   if(mode != st.st_mode)
  1106.     {
  1107.       if(chmod(fname,mode)!=0)
  1108.     {
  1109.       DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
  1110.       return(ERROR(ERRDOS,ERRnoaccess));
  1111.     }
  1112.     }
  1113.  
  1114.   /* Only try and change size on non-directories */
  1115.   if(!is_directory && (size != st.st_size))
  1116.     {
  1117.       if((fd = open(fname, O_RDWR))!= -1)
  1118.     {
  1119.       if(set_filelen(fd, size)!=0)
  1120.         {
  1121.           close(fd);
  1122.           return(ERROR(ERRDOS,ERRnoaccess));
  1123.         }
  1124.       close(fd);
  1125.     }
  1126.       else
  1127.     {
  1128.       DEBUG(2,("open of %s failed (%s)\n", fname, strerror(errno)));
  1129.       return(ERROR(ERRDOS,ERRnoaccess));
  1130.     }
  1131.     }
  1132.  
  1133.   SSVAL(params,0,0);
  1134.  
  1135.   send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0);
  1136.   
  1137.   return(-1);
  1138. }
  1139.  
  1140. /****************************************************************************
  1141.   reply to a TRANS2_QFILEINFO (query file info by fileid)
  1142. ****************************************************************************/
  1143.  
  1144. int call_trans2qfileinfo(char *inbuf, char *outbuf, int length, int bufsize,
  1145.             int cnum, char **pparams, char **ppdata)
  1146. {
  1147.   char *params = *pparams;
  1148.   char *pdata = *ppdata;
  1149.   uint16 info_level = SVAL(params,2);
  1150.   int mode=0;
  1151.   int size=0;
  1152.   int16 fnum = SVAL(params,0);
  1153.   unsigned int data_size;
  1154.   int outsize;
  1155.   struct stat sbuf;
  1156.   char *fname;
  1157.   BOOL ok = False;
  1158.  
  1159.   DEBUG(3,("call_trans2qfileinfo fnum = %d, info_level = %d\n", fnum, info_level));
  1160.  
  1161.   if((outsize = check_info_level(inbuf, outbuf, /* Needed for error return */ info_level)))
  1162.     return outsize;
  1163.  
  1164.   if (!OPEN_FNUM(fnum))
  1165.     return(ERROR(ERRDOS,ERRbadfid));
  1166.   if (Protocol >= PROTOCOL_LANMAN1)
  1167.     {
  1168.       if(HAS_CACHED_ERROR(fnum))
  1169.     return (CACHED_ERROR(fnum));
  1170.     }
  1171.  
  1172.   fname = Files[fnum].name;
  1173.  
  1174.   if (fstat(Files[fnum].fd,&sbuf) == 0)
  1175.     {
  1176.       mode = dos_mode(cnum,fname,&sbuf);
  1177.       size = sbuf.st_size;
  1178.       if (mode & aDIR)
  1179.     size = 0;
  1180.       ok = True;
  1181.     }
  1182.   else
  1183.     DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
  1184.   
  1185.   if (!ok)
  1186.     return(UNIXERROR(ERRDOS,ERRbadfid));
  1187.   
  1188.   /* Realloc the parameter and data sizes */
  1189.   params = *pparams = Realloc(*pparams,2);
  1190.   if(params == NULL)
  1191.     return(ERROR(ERRDOS,ERRnomem));
  1192.  
  1193.   data_size = (info_level == 1 ? 22 : 26);
  1194.  
  1195.   if(data_size > SVAL(inbuf, smb_mdrcnt))
  1196.     {
  1197.       DEBUG(3,("trans2qpathinfo : max_data = %d, data_size = %d\n",
  1198.         SVAL(inbuf,smb_mdrcnt), data_size));
  1199.     }
  1200.   pdata = *ppdata = Realloc(*ppdata, data_size);
  1201.   if(pdata == NULL)
  1202.     return(ERROR(ERRDOS,ERRnomem));
  1203.  
  1204.   /* No extended attribute errors */
  1205.   SSVAL(params,0,0);
  1206.  
  1207.   put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime);
  1208.   put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
  1209.   put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime);
  1210.   SIVAL(pdata,l1_cbFile,size);
  1211.   SIVAL(pdata,l1_cbFileAlloc,1024); /* Make 1024 for now */
  1212.   SSVAL(pdata,l1_attrFile,mode);
  1213.   if(info_level == 2)
  1214.     SIVAL(pdata,l2_cbList,0);
  1215.  
  1216.   send_trans2_replies( outbuf, bufsize, params, 2, pdata, data_size);
  1217.  
  1218.   DEBUG(3,("%s trans2qfileinfo fname = %s fnum=%d mode=%d size=%d\n",timestring(),fname,fnum,mode,size));
  1219.   
  1220.   return(-1);
  1221. }
  1222.  
  1223. /****************************************************************************
  1224.   reply to a TRANS2_SETFILEINFO (set file info by fileid)
  1225. ****************************************************************************/
  1226.  
  1227. int call_trans2setfileinfo(char *inbuf, char *outbuf, int length, int bufsize,
  1228.             int cnum, char **pparams, char **ppdata)
  1229. {
  1230.   char *params = *pparams;
  1231.   char *pdata = *ppdata;
  1232.   uint16 info_level = SVAL(params,2);
  1233.   int mode;
  1234.   int size;
  1235.   struct utimbuf tvs;
  1236.   struct stat st;
  1237.   int outsize;
  1238.   int16 fnum = SVAL(params,0);
  1239.   int fd;
  1240.   char *fname;
  1241.  
  1242.   DEBUG(3,("call_trans2setfileinfo fnum = %d, info_level = %d\n", fnum, info_level));
  1243.  
  1244.   if((outsize = check_info_level(inbuf, outbuf, /* Needed for error return */ info_level)))
  1245.     return outsize;
  1246.  
  1247.   if (!OPEN_FNUM(fnum))
  1248.     return(ERROR(ERRDOS,ERRbadfid));
  1249.  
  1250.   if (!CAN_WRITE(cnum))
  1251.     return(ERROR(ERRSRV,ERRaccess));
  1252.  
  1253.   if (Protocol >= PROTOCOL_LANMAN1)
  1254.     {
  1255.       if(HAS_CACHED_ERROR(fnum))
  1256.     return (CACHED_ERROR(fnum));
  1257.     }
  1258.  
  1259.   /* Realloc the parameter and data sizes */
  1260.   params = *pparams = Realloc(*pparams,2);
  1261.   if(params == NULL)
  1262.     return(ERROR(ERRDOS,ERRnomem));
  1263.  
  1264.   fd = Files[fnum].fd;
  1265.   fname = Files[fnum].name;
  1266.  
  1267.   if(fstat(fd,&st)!=0)
  1268.     {
  1269.       DEBUG(3,("fstat of fnum %d failed (%s)\n", fnum, strerror(errno)));
  1270.       return(ERROR(ERRDOS,ERRbadpath));
  1271.     }
  1272.  
  1273.   tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
  1274.   tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
  1275.   mode = unix_mode(cnum,SVAL(pdata,l1_attrFile));
  1276.   size = IVAL(pdata,l1_cbFile);
  1277.  
  1278.   /* Try and set the times, size and mode of this file - if they are different 
  1279.    from the current values */
  1280.   if(st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
  1281.     {
  1282.       if(utime(fname, &tvs)!=0)
  1283.     {
  1284.       DEBUG(2,("utime of %s (fnum %d) failed (%s)\n", fname, fnum, strerror(errno)));
  1285.       if(errno == ENOENT)
  1286.         return(ERROR(ERRDOS,ERRbadpath));
  1287.       return(ERROR(ERRDOS,ERRnoaccess));
  1288.     }
  1289.     }
  1290.   if(mode != st.st_mode)
  1291.     {
  1292.       if(chmod(fname,mode)!=0)
  1293.     {
  1294.       DEBUG(2,("chmod of %s (fnum %d) failed (%s)\n", fname, fnum, strerror(errno)));
  1295.       return(ERROR(ERRDOS,ERRnoaccess));
  1296.     }
  1297.     }
  1298.  
  1299.   if(size != st.st_size)
  1300.     {
  1301.       /* lan server seems to use size=0 as "don't set it" so we won't */
  1302.       if(size && set_filelen(fd, size)!=0)
  1303.     return(ERROR(ERRDOS,ERRnoaccess));
  1304.     }
  1305.  
  1306.   SSVAL(params,0,0);
  1307.  
  1308.   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
  1309.   
  1310.   return(-1);
  1311. }
  1312.  
  1313. /****************************************************************************
  1314.   reply to a TRANS2_MKDIR (make directory with extended attributes).
  1315. ****************************************************************************/
  1316.  
  1317. int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
  1318.             int cnum, char **pparams, char **ppdata)
  1319. {
  1320.   char *params = *pparams;
  1321.   pstring directory = "";
  1322.   int ret = -1;
  1323.  
  1324.   if (!CAN_WRITE(cnum))
  1325.     return(ERROR(ERRSRV,ERRaccess));
  1326.  
  1327.   strcpy(directory, ¶ms[4]);
  1328.  
  1329.   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
  1330.  
  1331.   unix_convert(directory,cnum);
  1332.   if (check_name(directory,cnum))
  1333.     ret = mkdir(directory,unix_mode(cnum,aDIR));
  1334.   
  1335.   if(ret < 0)
  1336.     {
  1337.       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
  1338.       return(UNIXERROR(ERRDOS,ERRnoaccess));
  1339.     }
  1340.  
  1341.   /* Realloc the parameter and data sizes */
  1342.   params = *pparams = Realloc(*pparams,2);
  1343.   if(params == NULL)
  1344.     return(ERROR(ERRDOS,ERRnomem));
  1345.  
  1346.   SSVAL(params,0,0);
  1347.  
  1348.   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
  1349.   
  1350.   return(-1);
  1351. }
  1352.  
  1353. /****************************************************************************
  1354.   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
  1355.   We don't actually do this - we just send a null response.
  1356. ****************************************************************************/
  1357.  
  1358. int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize,
  1359.             int cnum, char **pparams, char **ppdata)
  1360. {
  1361.   static uint16 fnf_handle = 257;
  1362.   char *params = *pparams;
  1363.   int outsize;
  1364.   uint16 info_level = SVAL(params,4);
  1365.  
  1366.   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
  1367.  
  1368.   if((outsize = check_info_level(inbuf, outbuf, /* Needed for error return */ info_level)))
  1369.     return outsize;
  1370.  
  1371.   /* Realloc the parameter and data sizes */
  1372.   params = *pparams = Realloc(*pparams,6);
  1373.   if(params == NULL)
  1374.     return(ERROR(ERRDOS,ERRnomem));
  1375.  
  1376.   SSVAL(params,0,fnf_handle);
  1377.   SSVAL(params,2,0); /* No changes */
  1378.   SSVAL(params,4,0); /* No EA errors */
  1379.  
  1380.   fnf_handle++;
  1381.  
  1382.   if(fnf_handle == 0)
  1383.     fnf_handle = 257;
  1384.  
  1385.   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
  1386.   
  1387.   return(-1);
  1388. }
  1389.  
  1390. /****************************************************************************
  1391.   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
  1392.   changes). Currently this does nothing.
  1393. ****************************************************************************/
  1394. int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize,
  1395.             int cnum, char **pparams, char **ppdata)
  1396. {
  1397.   char *params = *pparams;
  1398.  
  1399.   DEBUG(3,("call_trans2findnotifynext\n"));
  1400.  
  1401.   /* Realloc the parameter and data sizes */
  1402.   params = *pparams = Realloc(*pparams,4);
  1403.   if(params == NULL)
  1404.     return(ERROR(ERRDOS,ERRnomem));
  1405.  
  1406.   SSVAL(params,0,0); /* No changes */
  1407.   SSVAL(params,2,0); /* No EA errors */
  1408.  
  1409.   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
  1410.   
  1411.   return(-1);
  1412. }
  1413.  
  1414. /****************************************************************************
  1415.   reply to a SMBfindclose (stop trans2 directory search)
  1416. ****************************************************************************/
  1417. int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize)
  1418. {
  1419.   int cnum;
  1420.   int outsize = 0;
  1421.   uint16 dptr_num=SVAL(inbuf,smb_vwv0);
  1422.   void *dptr;
  1423.  
  1424.   cnum = SVAL(inbuf,smb_tid);
  1425.  
  1426.   DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
  1427.  
  1428.   if((dptr = dptr_get(dptr_num))==NULL)
  1429.     {
  1430.       /* Invalid dptr_num */
  1431.       DEBUG(5,("reply_findclose - dptr_num is bad\n"));
  1432.  
  1433.       return (ERROR(ERRDOS,ERRbadfid));
  1434.     }
  1435.  
  1436.   dptr_demote(dptr_num);
  1437.   dptr_close(dptr_num);
  1438.  
  1439.   outsize = set_message(outbuf,0,0,True);
  1440.  
  1441.   DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
  1442.  
  1443.   return(outsize);
  1444. }
  1445.  
  1446. /****************************************************************************
  1447.   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
  1448. ****************************************************************************/
  1449. int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize)
  1450. {
  1451.   int cnum;
  1452.   int outsize = 0;
  1453.   int dptr_num=-1;
  1454.  
  1455.   cnum = SVAL(inbuf,smb_tid);
  1456.   dptr_num = SVAL(inbuf,smb_vwv0);
  1457.  
  1458.   DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num));
  1459.  
  1460.   /* We never give out valid handles for a 
  1461.      findnotifyfirst - so any dptr_num is ok here. 
  1462.      Just ignore it. */
  1463.  
  1464.   outsize = set_message(outbuf,0,0,True);
  1465.  
  1466.   DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num));
  1467.  
  1468.   return(outsize);
  1469. }
  1470.  
  1471.  
  1472. /****************************************************************************
  1473.   reply to a SMBtrans2
  1474. ****************************************************************************/
  1475. int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
  1476. {
  1477.   int outsize = 0;
  1478.   int cnum = SVAL(inbuf,smb_tid);
  1479.   unsigned int total_params = SVAL(inbuf, smb_tpscnt);
  1480.   unsigned int total_data =SVAL(inbuf, smb_tdscnt);
  1481. #if 0
  1482.   unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
  1483.   unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
  1484.   unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
  1485.   BOOL close_tid = BITSETW(inbuf+smb_flags,0);
  1486.   BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
  1487.   int32 timeout = IVALS(inbuf,smb_timeout);
  1488. #endif
  1489.   unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
  1490.   unsigned int tran_call = SVAL(inbuf, smb_setup0);
  1491.   char *params = NULL, *data = NULL;
  1492.   int num_params, num_params_sofar, num_data, num_data_sofar;
  1493.  
  1494.   outsize = set_message(outbuf,0,0,True);
  1495.  
  1496.   /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
  1497.      is so as a sanity check */
  1498.   if(suwcnt != 1 )
  1499.     {
  1500.       DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
  1501.       return(ERROR(ERRSRV,ERRerror));
  1502.     }
  1503.     
  1504.   /* Allocate the space for the maximum needed parameters and data */
  1505.   if (total_params > 0)
  1506.     params = (char *)malloc(total_params);
  1507.   if (total_data > 0)
  1508.     data = (char *)malloc(total_data);
  1509.   
  1510.   if ((total_params && !params)  || (total_data && !data))
  1511.     {
  1512.       DEBUG(2,("Out of memory in reply_trans2\n"));
  1513.       return(ERROR(ERRDOS,ERRnomem));
  1514.     }
  1515.  
  1516.   /* Copy the param and data bytes sent with this request into
  1517.      the params buffer */
  1518.   num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
  1519.   num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
  1520.  
  1521.   memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
  1522.   memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
  1523.  
  1524.   if(num_data_sofar < total_data || num_params_sofar < total_params)
  1525.     {
  1526.     /* We need to send an interim response then receive the rest
  1527.        of the parameter/data bytes */
  1528.       outsize = set_message(outbuf,0,0,True);
  1529.       send_smb(outbuf);
  1530.  
  1531.       while( num_data_sofar < total_data || num_params_sofar < total_params)
  1532.     {
  1533.       receive_smb(inbuf, 0);
  1534.       
  1535.       /* Ensure this is still a trans2 packet (sanity check) */
  1536.       if(CVAL(inbuf, smb_com) != SMBtrans2)
  1537.         {
  1538.           outsize = set_message(outbuf,0,0,True);
  1539.           DEBUG(2,("Invalid secondary trans2 packet\n"));
  1540.           free(params);
  1541.           free(data);
  1542.           return(ERROR(ERRSRV,ERRerror));
  1543.         }
  1544.       
  1545.       /* Revise total_params and total_data in case they have changed downwards */
  1546.       total_params = SVAL(inbuf, smb_tpscnt);
  1547.       total_data = SVAL(inbuf, smb_tdscnt);
  1548.       num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
  1549.       num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
  1550.       memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)], 
  1551.          smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
  1552.       memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
  1553.          smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
  1554.     }
  1555.     }
  1556.  
  1557.   /* Now we must call the relevant TRANS2 function */
  1558.   switch( tran_call ) 
  1559.     {
  1560.     case TRANSACT2_OPEN:
  1561.       outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
  1562.       break;
  1563.     case TRANSACT2_FINDFIRST:
  1564.       outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data);
  1565.       break;
  1566.     case TRANSACT2_FINDNEXT:
  1567.       outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
  1568.       break;
  1569.     case TRANSACT2_QFSINFO:
  1570.       outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
  1571.       break;
  1572.     case TRANSACT2_SETFSINFO:
  1573.       outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
  1574.       break;
  1575.     case TRANSACT2_QPATHINFO:
  1576.       outsize = call_trans2qpathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
  1577.       break;
  1578.     case TRANSACT2_SETPATHINFO:
  1579.       outsize = call_trans2setpathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
  1580.       break;
  1581.     case TRANSACT2_QFILEINFO:
  1582.       outsize = call_trans2qfileinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
  1583.       break;
  1584.     case TRANSACT2_SETFILEINFO:
  1585.       outsize = call_trans2setfileinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
  1586.       break;
  1587.     case TRANSACT2_FINDNOTIFYFIRST:
  1588.       outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
  1589.       break;
  1590.     case TRANSACT2_FINDNOTIFYNEXT:
  1591.       outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
  1592.       break;
  1593.     case TRANSACT2_MKDIR:
  1594.       outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data);
  1595.       break;
  1596.     default:
  1597.       /* Error in request */
  1598.       DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call));
  1599.       if(params)
  1600.     free(params);
  1601.       if(data)
  1602.     free(data);
  1603.       return (ERROR(ERRSRV,ERRerror));
  1604.     }
  1605.  
  1606.   /* As we do not know how many data packets will need to be
  1607.      returned here the various call_trans2xxxx calls
  1608.      must send their own. Thus a call_trans2xxx routine only
  1609.      returns a value other than -1 when it wants to send
  1610.      an error packet. 
  1611.   */
  1612.  
  1613.   if(params)
  1614.     free(params);
  1615.   if(data)
  1616.     free(data);
  1617.   return outsize; /* If a correct response was needed the call_trans2xxx 
  1618.              calls have already sent it. If outsize != -1 then it is
  1619.              returning an error packet. */
  1620. }
  1621.