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 / reply.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  77.2 KB  |  3,126 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.8.
  4.    Copyright (C) Andrew Tridgell 1992,1993,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.    This file handles most of the reply_ calls that the server
  22.    makes to handle specific protocols
  23. */
  24.  
  25.  
  26. #include "includes.h"
  27. #include "loadparm.h"
  28. #include "trans2.h"
  29.  
  30. /* look in server.c for some explanation of these variables */
  31. extern int Protocol;
  32. extern int DEBUGLEVEL;
  33. extern int chain_size;
  34. extern int maxxmit;
  35. extern int num_files_open;
  36. extern int chain_fnum;
  37. extern char magic_char;
  38. extern BOOL long_filenames;
  39. extern BOOL casesignames;
  40. extern connection_struct Connections[];
  41. extern files_struct Files[];
  42.  
  43. /* this macro should always be used to extract an fnum (smb_fid) from
  44. a packet to ensure chaining works correctly */
  45. #define GETFNUM(buf,where) (chain_fnum!=-1?chain_fnum:SVAL(buf,where))
  46.  
  47. /****************************************************************************
  48.   reply to an special message 
  49. ****************************************************************************/
  50. int reply_special(char *inbuf,char *outbuf)
  51. {
  52.   int outsize = 4;
  53.   int msg_type = CVAL(inbuf,0);
  54.   int msg_flags = CVAL(inbuf,1);
  55.   pstring name1="";
  56.   pstring name2="";
  57.  
  58.   switch (msg_type)
  59.     {
  60.     case 0x81: /* session request */
  61.       CVAL(outbuf,0) = 0x82;
  62.       CVAL(outbuf,3) = 0;
  63.       name_interpret(inbuf + 4,name1);
  64.       name_interpret(inbuf + 4 + name_len(inbuf + 4),name2);
  65.       DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));      
  66.       {
  67.     char *p;
  68.     extern fstring remote_machine;
  69.     strcpy(remote_machine,name2);
  70.     trim_string(remote_machine," "," ");
  71.     p = strchr(remote_machine,' ');
  72.     if (p) *p = 0;
  73.       }
  74.       if (Get_Pwnam(name2))
  75.     add_session_user(name2);
  76.       break;
  77.     case 0x85: /* session keepalive */
  78.     default:
  79.       return(0);
  80.     }
  81.   
  82.   DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
  83.   
  84.   smb_setlen(outbuf,0);
  85.   return(outsize);
  86. }
  87.  
  88.  
  89.  
  90. /****************************************************************************
  91.   reply to a tcon
  92. ****************************************************************************/
  93. int reply_tcon(char *inbuf,char *outbuf)
  94. {
  95.   pstring service="";
  96.   pstring user="";
  97.   pstring password="";
  98.   pstring dev="";
  99.   int connection_num;
  100.   int outsize = 0;
  101.   int uid = SVAL(inbuf,smb_uid);
  102.   int vuid;
  103.  
  104.   vuid = valid_uid(uid);
  105.   
  106.   parse_connect(inbuf,service,user,password,dev);
  107.  
  108.   connection_num = make_connection(service,user,password,dev,vuid);
  109.   
  110.   if (connection_num < 0)
  111.     switch (connection_num)
  112.       {
  113.       case -4:
  114.     return(ERROR(ERRSRV,ERRaccess));
  115.       case -3:
  116.     return(ERROR(ERRDOS,ERRnoipc));
  117.       case -2:
  118.     return(ERROR(ERRSRV,ERRinvnetname));
  119.       default:
  120.     return(ERROR(ERRSRV,ERRbadpw));
  121.       }
  122.   
  123.   outsize = set_message(outbuf,2,0,True);
  124.   SSVAL(outbuf,smb_vwv0,MIN(lp_maxxmit(),BUFFER_SIZE)-4);
  125.   SSVAL(outbuf,smb_vwv1,connection_num);
  126.   SSVAL(outbuf,smb_tid,connection_num);
  127.   
  128.   DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
  129.   
  130.   return(outsize);
  131. }
  132.  
  133.  
  134. /****************************************************************************
  135.   reply to a tcon and X
  136. ****************************************************************************/
  137. int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
  138. {
  139.   pstring service="";
  140.   pstring user="";
  141.   pstring password="";
  142.   pstring devicename="";
  143.   int connection_num;
  144.   int outsize = 0;
  145.   int uid = SVAL(inbuf,smb_uid);
  146.   int vuid;
  147.   int smb_com2 = SVAL(inbuf,smb_vwv0);
  148.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  149.   
  150.   /* we might have to close an old one */
  151.   if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
  152.     close_cnum(SVAL(inbuf,smb_tid));
  153.   
  154.   vuid = valid_uid(uid);
  155.   
  156.   {
  157.     int passlen = SVAL(inbuf,smb_vwv3);
  158.     char *path;
  159.     char *p;
  160.     memcpy(password,smb_buf(inbuf),passlen);
  161.     password[passlen]=0;
  162.     path = smb_buf(inbuf) + passlen;
  163.     DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
  164.     strcpy(service,path+2);
  165.     p = strchr(service,'\\');
  166.     if (!p)
  167.       return(ERROR(ERRSRV,ERRinvnetname));
  168.     *p = 0;
  169.     strcpy(service,p+1);
  170.     p = strchr(service,'%');
  171.     if (p)
  172.       {
  173.     *p++ = 0;
  174.     strcpy(user,p);
  175.       }
  176.     strcpy(devicename,path + strlen(path) + 1);  
  177.     DEBUG(4,("Got device type %s\n",devicename));
  178.   }
  179.  
  180.   connection_num = make_connection(service,user,password,devicename,vuid);
  181.   
  182.   if (connection_num < 0)
  183.     switch (connection_num)
  184.       {
  185.       case -4:
  186.     return(ERROR(ERRSRV,ERRaccess));
  187.       case -3:
  188.     return(ERROR(ERRDOS,ERRnoipc));
  189.       case -2:
  190.     return(ERROR(ERRSRV,ERRinvnetname));
  191.       default:
  192.     return(ERROR(ERRSRV,ERRbadpw));
  193.       }
  194.   
  195.   outsize = set_message(outbuf,2,strlen(devicename)+1,True);
  196.   
  197.   DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
  198.   
  199.   /* set the incoming and outgoing tid to the just created one */
  200.   SSVAL(inbuf,smb_tid,connection_num);
  201.   SSVAL(outbuf,smb_tid,connection_num);
  202.  
  203.   CVAL(outbuf,smb_vwv0) = smb_com2;
  204.   SSVAL(outbuf,smb_vwv1,(chain_size + outsize)-4);
  205.  
  206.   strcpy(smb_buf(outbuf),devicename);
  207.  
  208.   if (smb_com2 != 0xFF)
  209.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  210.                outbuf,outbuf+outsize,
  211.                length,bufsize);
  212.  
  213.   return(outsize);
  214. }
  215.  
  216.  
  217. /****************************************************************************
  218.   reply to an unknown type
  219. ****************************************************************************/
  220. int reply_unknown(char *inbuf,char *outbuf)
  221. {
  222.   int cnum;
  223.   int type;
  224.   cnum = SVAL(inbuf,smb_tid);
  225.   type = CVAL(inbuf,smb_com);
  226.   
  227.   DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
  228.     timestring(),
  229.     smb_fn_name(type),
  230.     cnum,type,type));
  231.   
  232.   return(ERROR(ERRSRV,ERRnosupport));
  233. }
  234.  
  235.  
  236. /****************************************************************************
  237.   reply to an ioctl
  238. ****************************************************************************/
  239. int reply_ioctl(char *inbuf,char *outbuf)
  240. {
  241.   DEBUG(3,("ignoring ioctl\n"));
  242.   
  243.   return(ERROR(ERRSRV,ERRnosupport));
  244. }
  245.  
  246.  
  247. /****************************************************************************
  248. reply to a session setup command
  249. ****************************************************************************/
  250. int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
  251. {
  252.   int outsize = 0;
  253.   int sess_uid;
  254.   int   smb_com2;
  255.   int   smb_off2;       
  256.   int   smb_bufsize;    
  257.   int   smb_mpxmax;     
  258.   int   smb_vc_num;     
  259.   uint32   smb_sesskey;    
  260.   int   smb_apasslen;   
  261.   pstring smb_apasswd="";
  262.   pstring smb_aname="";    
  263.   BOOL guest=False;
  264.   
  265.   sess_uid = SVAL(inbuf,smb_uid);
  266.   smb_com2 = CVAL(inbuf,smb_vwv0);
  267.   smb_off2 = SVAL(inbuf,smb_vwv1);
  268.   smb_bufsize = SVAL(inbuf,smb_vwv2);
  269.   smb_mpxmax = SVAL(inbuf,smb_vwv3);
  270.   smb_vc_num = SVAL(inbuf,smb_vwv4);
  271.   smb_sesskey = IVAL(inbuf,smb_vwv5);
  272.   smb_apasslen = SVAL(inbuf,smb_vwv7);
  273.  
  274.   StrnCpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
  275.   StrnCpy(smb_aname,smb_buf(inbuf)+smb_apasslen,sizeof(smb_aname)-1);
  276.  
  277.   DEBUG(3,("sesssetupX:name=[%s]\n",smb_aname));
  278.  
  279.   strlower(smb_aname);
  280.  
  281.   if (Get_Pwnam(smb_aname))
  282.     add_session_user(smb_aname);
  283.  
  284.   if (!check_hosts_equiv(smb_aname))
  285.     {
  286.  
  287.       if (strequal(smb_aname,lp_guestaccount()) && (*smb_apasswd == 0))
  288.     guest = True;
  289.   
  290.       /* now check if it's a valid username/password */
  291.       if (!guest && !password_ok(smb_aname,smb_apasswd, NULL))
  292.     {
  293.       DEBUG(3,("Registered username %s for guest access\n",smb_aname));
  294.        if (*smb_apasswd || !Get_Pwnam(smb_aname))
  295.         strcpy(smb_aname,lp_guestaccount());
  296.       guest = True;
  297.     }
  298.     }
  299.  
  300.   if (!strequal(smb_aname,lp_guestaccount()))
  301.     {
  302.       int homes = lp_servicenumber(HOMES_NAME);
  303.       char *home = get_home_dir(smb_aname);
  304.       if (homes >= 0 && home)
  305.     lp_add_home(smb_aname,homes,home);
  306.     }
  307.  
  308.  
  309.   /* it's ok - setup a reply */
  310.   outsize = set_message(outbuf,3,0,True);
  311.  
  312.   CVAL(outbuf,smb_vwv0) = smb_com2;
  313.   SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
  314.  
  315.   if (guest)
  316.     SSVAL(outbuf,smb_vwv2,1);
  317.  
  318.   /* register the name and uid as being validated, so further connections
  319.      to a uid can get through without a password, on the same VC */
  320.   register_uid(SVAL(inbuf,smb_uid),smb_aname,guest);
  321.   
  322.   if (smb_com2 != 0xFF)
  323.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  324.                outbuf,outbuf+outsize,
  325.                length,bufsize);
  326.  
  327.   maxxmit = MIN(lp_maxxmit(),smb_bufsize);
  328.  
  329.   return(outsize);
  330. }
  331.  
  332.  
  333. /****************************************************************************
  334.   reply to a chkpth
  335. ****************************************************************************/
  336. int reply_chkpth(char *inbuf,char *outbuf)
  337. {
  338.   int outsize = 0;
  339.   int cnum,mode;
  340.   pstring name="";
  341.   BOOL ok = False;
  342.   
  343.   cnum = SVAL(inbuf,smb_tid);
  344.   
  345.   strcpy(name,smb_buf(inbuf) + 1);
  346.   unix_convert(name,cnum);
  347.  
  348.   mode = SVAL(inbuf,smb_vwv0);
  349.  
  350.   if (check_name(name,cnum))
  351.     ok = directory_exist(name);
  352.  
  353.   if (!ok)
  354.     return(ERROR(ERRDOS,ERRbadpath));
  355.   
  356.   outsize = set_message(outbuf,0,0,True);
  357.   
  358.   DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
  359.   
  360.   return(outsize);
  361. }
  362.  
  363.  
  364. /****************************************************************************
  365.   reply to a getatr
  366. ****************************************************************************/
  367. int reply_getatr(char *inbuf,char *outbuf)
  368. {
  369.   pstring fname="";
  370.   int cnum;
  371.   int outsize = 0;
  372.   struct stat sbuf;
  373.   BOOL ok = False;
  374.   int mode=0;
  375.   uint32 size=0;
  376.   time_t mtime=0;
  377.   
  378.   cnum = SVAL(inbuf,smb_tid);
  379.  
  380.   strcpy(fname,smb_buf(inbuf) + 1);
  381.   unix_convert(fname,cnum);
  382.  
  383.   /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
  384.      under WfWg - weird! */
  385.   if (! (*fname))
  386.     {
  387.       mode = 0x12;
  388.       size = 0;
  389.       mtime = 0;
  390.       ok = True;
  391.     }
  392.   else
  393.     if (check_name(fname,cnum))
  394.       {
  395.     if (stat(fname,&sbuf) == 0)
  396.       {
  397.         mode = dos_mode(cnum,fname,&sbuf);
  398.         size = sbuf.st_size;
  399.         mtime = sbuf.st_mtime;
  400.         if (mode & aDIR)
  401.           size = 0;
  402.         ok = True;
  403.       }
  404.     else
  405.       DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
  406.     }
  407.   
  408.   if (!ok)
  409.     return(UNIXERROR(ERRDOS,ERRbadfile));
  410.   
  411.   outsize = set_message(outbuf,10,0,True);
  412.  
  413.   SSVAL(outbuf,smb_vwv0,mode);
  414.   SIVAL(outbuf,smb_vwv1,mtime + GMT_TO_LOCAL * TimeDiff());
  415.   SIVAL(outbuf,smb_vwv3,size);
  416.   
  417.   DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
  418.   
  419.   return(outsize);
  420. }
  421.  
  422.  
  423. /****************************************************************************
  424.   reply to a setatr
  425. ****************************************************************************/
  426. int reply_setatr(char *inbuf,char *outbuf)
  427. {
  428.   pstring fname="";
  429.   int cnum;
  430.   int outsize = 0;
  431.   BOOL ok=False;
  432.   int mode;
  433.   time_t mtime;
  434.   
  435.   cnum = SVAL(inbuf,smb_tid);
  436.   
  437.   strcpy(fname,smb_buf(inbuf) + 1);
  438.   unix_convert(fname,cnum);
  439.  
  440.   mode = SVAL(inbuf,smb_vwv0);
  441.   mtime = IVAL(inbuf,smb_vwv1);
  442.   
  443.   if (directory_exist(fname))
  444.     mode |= aDIR;
  445.   if (check_name(fname,cnum))
  446.     ok =  (chmod(fname,unix_mode(cnum,mode)) == 0);
  447.   if (ok && mtime != 0)
  448.     ok = set_filetime(fname,mtime + LOCAL_TO_GMT * TimeDiff());
  449.   
  450.   if (!ok)
  451.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  452.   
  453.   outsize = set_message(outbuf,0,0,True);
  454.   
  455.   DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
  456.   
  457.   return(outsize);
  458. }
  459.  
  460.  
  461. /****************************************************************************
  462.   reply to a dskattr
  463. ****************************************************************************/
  464. int reply_dskattr(char *inbuf,char *outbuf)
  465. {
  466.   int cnum;
  467.   int outsize = 0;
  468.   int dfree,dsize,bsize;
  469.   
  470.   cnum = SVAL(inbuf,smb_tid);
  471.   
  472.   disk_free(".",&bsize,&dfree,&dsize);
  473.   
  474.   outsize = set_message(outbuf,5,0,True);
  475.   
  476.   SSVAL(outbuf,smb_vwv0,dsize);
  477.   SSVAL(outbuf,smb_vwv1,1);
  478.   SSVAL(outbuf,smb_vwv2,bsize);
  479.   SSVAL(outbuf,smb_vwv3,dfree);
  480.   
  481.   DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
  482.   
  483.   return(outsize);
  484. }
  485.  
  486.  
  487. /****************************************************************************
  488.   reply to a search
  489.   Can be called from SMBsearch, SMBffirst or SMBfunique.
  490. ****************************************************************************/
  491. int reply_search(char *inbuf,char *outbuf)
  492. {
  493.   pstring mask="";
  494.   pstring directory="";
  495.   pstring fname="";
  496.   int size,mode;
  497.   time_t date;
  498.   int dirtype;
  499.   int cnum;
  500.   int outsize = 0;
  501.   int numentries = 0;
  502.   BOOL finished = False;
  503.   int maxentries;
  504.   int i;
  505.   char *p;
  506.   BOOL ok = False;
  507.   int status_len;
  508.   char *path;
  509.   char status[21];
  510.   int dptr_num=-1;
  511.   BOOL check_descend = False;
  512.   BOOL expect_close = False;
  513.  
  514.   /* If we were called as SMBffirst then we must expect close. */
  515.   if(CVAL(inbuf,smb_com) == SMBffirst)
  516.     expect_close = True;
  517.   
  518.   cnum = SVAL(inbuf,smb_tid);
  519.  
  520.   outsize = set_message(outbuf,1,3,True);
  521.   maxentries = SVAL(inbuf,smb_vwv0); 
  522.   dirtype = SVAL(inbuf,smb_vwv1);
  523.   path = smb_buf(inbuf) + 1;
  524.   status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
  525.  
  526.   
  527.   /* dirtype &= ~aDIR; */
  528.   
  529.   DEBUG(5,("path=%s status_len=%d\n",path,status_len));
  530.  
  531.   
  532.   if (status_len == 0)
  533.     {
  534.       pstring dir2;
  535.  
  536.       strcpy(directory,smb_buf(inbuf)+1);
  537.       strcpy(dir2,smb_buf(inbuf)+1);
  538.       unix_convert(directory,cnum);
  539.       unix_format(dir2);
  540.  
  541.       if (!check_name(directory,cnum))
  542.     return(ERROR(ERRDOS,ERRbadpath));
  543.  
  544.       p = strrchr(dir2,'/');
  545.       if (p == NULL) 
  546.     {strcpy(mask,dir2);*dir2 = 0;}
  547.       else
  548.     {*p = 0;strcpy(mask,p+1);}
  549.  
  550.       p = strrchr(directory,'/');
  551.       if (!p) 
  552.     *directory = 0;
  553.       else
  554.     *p = 0;
  555.  
  556.       if (strlen(directory) == 0)
  557.     strcpy(directory,"./");
  558.       memset(status,0,21);
  559.       CVAL(status,0) = dirtype;
  560.     }
  561.   else
  562.     {
  563.       memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
  564.       memcpy(mask,status+1,11);
  565.       mask[11] = 0;
  566.       Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);      
  567.       dirtype = CVAL(status,0) & 0x1F;
  568.       if (!Connections[cnum].dirptr)
  569.     return(ERROR(ERRDOS,ERRnofiles));
  570.       StrnCpy(Connections[cnum].dirpath,dptr_path(dptr_num),sizeof(pstring)-1);
  571.       strlower(mask);
  572.     }
  573.   
  574.  
  575.   DEBUG(5,("mask=%s directory=%s\n",mask,directory));
  576.   CVAL(smb_buf(outbuf),0) = 5;
  577.   
  578.     {
  579.       char *p = smb_buf(outbuf) + 3;
  580.       
  581.       ok = True;
  582.       
  583.       if (status_len == 0)
  584.     {
  585.       if (!start_dir(cnum,directory))
  586.         ok = False;
  587.       else
  588.         {
  589.           /* close any old instances of this directory being open */
  590. #if 0
  591.           dptr_closepath(directory,SVAL(inbuf,smb_pid));
  592. #endif
  593.  
  594.           dptr_num = dptr_create(Connections[cnum].dirptr,directory,
  595.                      expect_close,SVAL(inbuf,smb_pid));
  596.           if (dptr_num < 0)
  597.         {
  598.           if(Connections[cnum].dirptr != NULL)
  599.             closedir(Connections[cnum].dirptr);
  600.           return(ERROR(ERRDOS,ERRnofids));
  601.         }
  602.         }
  603.     }
  604.  
  605.       DEBUG(3,("dptr_num is %d\n",dptr_num));
  606.  
  607.       if (ok)
  608.     {
  609.       if ((dirtype&0x1F) == aVOLID)
  610.         {      
  611.           memcpy(p,status,21);
  612.           make_dir_struct(p,"???????????",SERVICE(SNUM(cnum)),0,aVOLID,0);
  613.           dptr_fill(p+12,dptr_num);
  614.           if (dptr_zero(p+12) && (status_len==0))
  615.         numentries = 1;
  616.           else
  617.         numentries = 0;
  618.           p += DIR_STRUCT_SIZE;
  619.         }
  620.       else 
  621.         {
  622.           DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
  623.           if (in_list(Connections[cnum].dirpath,
  624.               lp_dontdescend(SNUM(cnum)),True))
  625.         check_descend = True;
  626.  
  627.           for (i=numentries;(i<maxentries) && !finished;i++)
  628.         {
  629.           finished = 
  630.             !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
  631.           if (!finished)
  632.             {
  633.               memcpy(p,status,21);
  634.               make_dir_struct(p,mask,fname,size,mode,date);
  635.               dptr_fill(p+12,dptr_num);
  636.               numentries++;
  637.             }
  638.           p += DIR_STRUCT_SIZE;
  639.         }
  640.         }
  641.     }
  642.     }
  643. #if 1
  644.   if ((numentries == 0 && status_len != 0) || !ok)
  645. #else
  646.     if (finished || !ok)
  647. #endif
  648.       {
  649.     CVAL(outbuf,smb_rcls) = ERRDOS;
  650.     SSVAL(outbuf,smb_err,ERRnofiles);
  651.     if (dptr_num >= 0)
  652.       dptr_demote(dptr_num);
  653.       }
  654.  
  655.   /* If we were called as SMBffirst with smb_search_id == NULL
  656.      and no entries were found then return error and close dirptr 
  657.      (X/Open spec) */
  658.  
  659.   if(ok && expect_close && numentries == 0 && status_len == 0)
  660.     {
  661.       CVAL(outbuf,smb_rcls) = ERRDOS;
  662.       SSVAL(outbuf,smb_err,ERRnofiles);
  663.       /* Also close the dptr - we know it's gone */
  664.       dptr_demote(dptr_num);
  665.       dptr_close(dptr_num);
  666.     }
  667.  
  668.   /* If we were called as SMBfunique, then we can close the dirptr now ! */
  669.   if(CVAL(inbuf,smb_com) == SMBfunique)
  670.     {
  671.       dptr_demote(dptr_num);
  672.       dptr_close(dptr_num);
  673.     }
  674.  
  675.   SSVAL(outbuf,smb_vwv0,numentries);
  676.   SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
  677.   CVAL(smb_buf(outbuf),0) = 5;
  678.   SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
  679.   
  680.   outsize += DIR_STRUCT_SIZE*numentries;
  681.   smb_setlen(outbuf,outsize - 4);
  682.   
  683.   if ((! *directory) && dptr_path(dptr_num))
  684.     sprintf(directory,"(%s)",dptr_path(dptr_num));
  685.  
  686.   DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n",
  687.     timestring(),
  688.     smb_fn_name(CVAL(inbuf,smb_com)), 
  689.     mask,directory,cnum,dirtype,numentries));
  690.  
  691.   return(outsize);
  692. }
  693.  
  694.  
  695. /****************************************************************************
  696.   reply to a fclose (stop directory search)
  697. ****************************************************************************/
  698. int reply_fclose(char *inbuf,char *outbuf)
  699. {
  700.   int cnum;
  701.   int outsize = 0;
  702.   int status_len;
  703.   char *path;
  704.   char status[21];
  705.   int dptr_num=-1;
  706.  
  707.   cnum = SVAL(inbuf,smb_tid);
  708.  
  709.   outsize = set_message(outbuf,1,0,True);
  710.   path = smb_buf(inbuf) + 1;
  711.   status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
  712.  
  713.   
  714.   if (status_len == 0)
  715.     return(ERROR(ERRSRV,ERRsrverror));
  716.  
  717.   memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
  718.  
  719.   if(!dptr_fetch(status+12,&dptr_num))
  720.     return(ERROR(ERRSRV,ERRsrverror));
  721.   
  722.   /*  Close the dptr - we know it's gone */
  723.   dptr_demote(dptr_num);
  724.   dptr_close(dptr_num);
  725.  
  726.   SSVAL(outbuf,smb_vwv0,0);
  727.  
  728.   DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
  729.  
  730.   return(outsize);
  731. }
  732.  
  733.  
  734. /****************************************************************************
  735.   reply to an open
  736. ****************************************************************************/
  737. int reply_open(char *inbuf,char *outbuf)
  738. {
  739.   pstring fname="";
  740.   int cnum;
  741.   int fnum = -1;
  742.   int outsize = 0;
  743.   int mode,share,fmode=0,attribute;
  744.   int openmode = 0;
  745.   int size = 0;
  746.   time_t mtime=0;
  747.   int unixmode;
  748.   int rmode;
  749.   struct stat sbuf;
  750.  
  751.   cnum = SVAL(inbuf,smb_tid);
  752.  
  753.   share = SVAL(inbuf,smb_vwv0);
  754.   mode = share & 0xF;
  755. #if 0
  756.   attribute = SVAL(inbuf,smb_vwv1);
  757. #else
  758.   /* X/Open says to ignore this */
  759.   attribute = aARCH;
  760. #endif
  761.   strcpy(fname,smb_buf(inbuf)+1);
  762.   unix_convert(fname,cnum);
  763.   
  764.   rmode = mode;
  765.  
  766.   switch (mode)
  767.     {
  768.     case 0: 
  769.       openmode = O_RDONLY; 
  770.       break;
  771.     case 1: 
  772.       openmode = O_WRONLY; 
  773.       break;
  774.     case 0xF: 
  775.       mode = 2;      
  776.     case 2: 
  777.       openmode = O_RDWR; 
  778.       break;
  779.     default:
  780.       rmode = 0;
  781.       openmode = O_RDONLY;
  782.       break;
  783.     }
  784.   
  785.   fnum = find_free_file();
  786.   if (fnum < 0)
  787.     return(ERROR(ERRSRV,ERRnofids));
  788.  
  789.   if (!check_name(fname,cnum))
  790.     return(ERROR(ERRDOS,ERRnoaccess));
  791.   
  792.   unixmode = unix_mode(cnum,attribute);
  793.       
  794.   open_file(fnum,cnum,fname,openmode,unixmode);      
  795.  
  796.   if (!Files[fnum].open)
  797.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  798.  
  799.   if (fstat(Files[fnum].fd,&sbuf) != 0)
  800.     {
  801.       close_file(fnum);
  802.       return(ERROR(ERRDOS,ERRnoaccess));
  803.     }
  804.     
  805.   size = sbuf.st_size;
  806.   fmode = dos_mode(cnum,fname,&sbuf);
  807.   mtime = sbuf.st_mtime;
  808.  
  809.   if (fmode & aDIR)
  810.     {
  811.       DEBUG(3,("attempt to open a directory %s\n",fname));
  812.       close_file(fnum);
  813.       return(ERROR(ERRDOS,ERRnoaccess));
  814.     }
  815.   
  816.  
  817.   outsize = set_message(outbuf,7,0,True);
  818.   SSVAL(outbuf,smb_vwv0,fnum);
  819.   SSVAL(outbuf,smb_vwv1,fmode);
  820.   SIVAL(outbuf,smb_vwv2,mtime + GMT_TO_LOCAL * TimeDiff());
  821.   SIVAL(outbuf,smb_vwv4,size);
  822.   SSVAL(outbuf,smb_vwv6,rmode);
  823.   
  824.   DEBUG(2,("opened file %s for %s\n",fname,openmode==O_RDONLY?"reading":"writing"));
  825.   DEBUG(3,("%s open %s fd=%d fnum=%d cnum=%d mode=%d omode=%d (numopen=%d)\n",timestring(),fname,Files[fnum].fd,fnum,cnum,mode,openmode,num_files_open));
  826.   
  827.   return(outsize);
  828. }
  829.  
  830.  
  831. /****************************************************************************
  832.   reply to an open and X
  833. ****************************************************************************/
  834. int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
  835. {
  836.   pstring fname="";
  837.   int cnum = SVAL(inbuf,smb_tid);
  838.   int fnum = -1;
  839.   int outsize = 0;
  840.   int openmode = 0;
  841.   int smb_com2 = CVAL(inbuf,smb_vwv0);
  842.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  843.   int smb_mode = SVAL(inbuf,smb_vwv3);
  844.   int smb_attr = SVAL(inbuf,smb_vwv5);
  845. #if 0
  846.   int smb_flags = SVAL(inbuf,smb_vwv2);
  847.   int smb_sattr = SVAL(inbuf,smb_vwv4); 
  848.   uint32 smb_time = IVAL(inbuf,smb_vwv6);
  849. #endif
  850.   int smb_ofun = SVAL(inbuf,smb_vwv8);
  851.   BOOL file_existed = False;
  852.   int unixmode;
  853.   int size=0,fmode=0,mtime=0,rmode;
  854.   struct stat sbuf;
  855.  
  856.   /* XXXX we need to handle passed times, sattr and flags */
  857.  
  858.   strcpy(fname,smb_buf(inbuf));
  859.   unix_convert(fname,cnum);
  860.   
  861.   rmode = smb_mode & 0x7;
  862.  
  863.   switch (smb_mode & 0x7)
  864.     {
  865.     case 0:       
  866.       openmode = O_RDONLY; 
  867.       break;
  868.     case 1: 
  869.       openmode = O_WRONLY; 
  870.       break;
  871.     case 0x7: 
  872.     case 2: 
  873.       rmode = 2;
  874.       openmode = O_RDWR; 
  875.       break;
  876.     case 3:  /* map execute to read */
  877.       openmode = O_RDONLY; 
  878.       break;
  879.     default:
  880.       rmode = 0;
  881.       openmode = O_RDONLY;
  882.       break;
  883.     }
  884.   
  885.   /* now add create and trunc bits */
  886.   if (smb_ofun & 0x10)
  887.     openmode |= O_CREAT;
  888.   if ((smb_ofun & 0x3) == 2)
  889.     openmode |= O_TRUNC;
  890.   
  891.   fnum = find_free_file();
  892.   if (fnum < 0)
  893.     return(ERROR(ERRSRV,ERRnofids));
  894.  
  895.   if (!check_name(fname,cnum))
  896.     return(ERROR(ERRDOS,ERRnoaccess));
  897.  
  898.   unixmode = unix_mode(cnum,smb_attr);
  899.       
  900.   file_existed = file_exist(fname);
  901.       
  902.   if ((smb_ofun & 0x3) == 0 && file_existed)
  903.     return(ERROR(ERRDOS,ERRfilexists));
  904.       
  905.   open_file(fnum,cnum,fname,openmode,unixmode);
  906.       
  907.   if (!Files[fnum].open)
  908.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  909.     
  910.   if (fstat(Files[fnum].fd,&sbuf) != 0)
  911.     {
  912.       close_file(fnum);
  913.       return(ERROR(ERRDOS,ERRnoaccess));
  914.     }
  915.  
  916.   size = sbuf.st_size;
  917.   fmode = dos_mode(cnum,fname,&sbuf);
  918.   mtime = sbuf.st_mtime;
  919.   if (fmode & aDIR)
  920.     {
  921.       close_file(fnum);
  922.       return(ERROR(ERRDOS,ERRnoaccess));
  923.     }
  924.   
  925.   outsize = set_message(outbuf,15,0,True);
  926.   CVAL(outbuf,smb_vwv0) = smb_com2;
  927.   SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
  928.   SSVAL(outbuf,smb_vwv2,fnum);
  929.   SSVAL(outbuf,smb_vwv3,fmode);
  930.   SIVAL(outbuf,smb_vwv4,mtime + GMT_TO_LOCAL * TimeDiff());
  931.   SIVAL(outbuf,smb_vwv6,size);
  932.   SSVAL(outbuf,smb_vwv8,rmode);
  933.  
  934.   {
  935.     int smb_action = 0;
  936.     
  937.     if (file_existed && !(openmode & O_TRUNC)) smb_action = 1;
  938.     if (!file_existed) smb_action = 2;
  939.     if (file_existed && (openmode & O_TRUNC)) smb_action = 3;
  940.  
  941.     /* if they requested a opportunistic lock and they have it read-only
  942.        then tell them they have it - this is wrong but it might work */
  943.     if ((CVAL(inbuf,smb_flg) & 0x20) && openmode == O_RDONLY)
  944.       smb_action |= 0x8000;
  945.     
  946.     SSVAL(outbuf,smb_vwv11,smb_action);
  947.   }
  948.  
  949.  
  950.   DEBUG(2,("opened file %s for %s\n",fname,openmode==O_RDONLY?"reading":"writing"));
  951.   DEBUG(2,("%s openX %s fd=%d fnum=%d cnum=%d mode=%d omode=%d (numopen=%d)\n",
  952.     timestring(),fname,Files[fnum].fd,fnum,cnum,
  953.     smb_mode,openmode,num_files_open));
  954.  
  955.   chain_fnum = fnum;
  956.  
  957.   if (smb_com2 != 0xFF)
  958.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  959.                outbuf,outbuf+outsize,
  960.                length,bufsize);
  961.  
  962.   chain_fnum = -1;
  963.   
  964.   return(outsize);
  965. }
  966.  
  967.  
  968. /****************************************************************************
  969.   reply to a mknew
  970. ****************************************************************************/
  971. int reply_mknew(char *inbuf,char *outbuf)
  972. {
  973.   pstring fname="";
  974.   int cnum,com;
  975.   int fnum = -1;
  976.   int outsize = 0;
  977.   int createmode;
  978.   mode_t unixmode;
  979.   
  980.   com = SVAL(inbuf,smb_com);
  981.   cnum = SVAL(inbuf,smb_tid);
  982.  
  983.   createmode = SVAL(inbuf,smb_vwv0);
  984.   strcpy(fname,smb_buf(inbuf)+1);
  985.   unix_convert(fname,cnum);
  986.  
  987.   if (createmode & aVOLID)
  988.     {
  989.       DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
  990.     }
  991.   
  992.   unixmode = unix_mode(cnum,createmode);
  993.   
  994.   if (com == SMBmknew && file_exist(fname))
  995.     return(ERROR(ERRDOS,ERRfilexists));
  996.     
  997.   fnum = find_free_file();
  998.   if (fnum < 0)
  999.     return(ERROR(ERRSRV,ERRnofids));
  1000.  
  1001.   if (!check_name(fname,cnum))
  1002.     return(ERROR(ERRDOS,ERRnoaccess));
  1003.  
  1004.   open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode);
  1005.   
  1006.   if (!Files[fnum].open)
  1007.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1008.   
  1009.   outsize = set_message(outbuf,1,0,True);
  1010.   SSVAL(outbuf,smb_vwv0,fnum);
  1011.   
  1012.   DEBUG(2,("new file %s\n",fname));
  1013.   DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd,fnum,cnum,createmode,unixmode));
  1014.   
  1015.   return(outsize);
  1016. }
  1017.  
  1018.  
  1019. /****************************************************************************
  1020.   reply to a create temporary file
  1021. ****************************************************************************/
  1022. int reply_ctemp(char *inbuf,char *outbuf)
  1023. {
  1024.   pstring fname="";
  1025.   pstring fname2="";
  1026.   int cnum;
  1027.   int fnum = -1;
  1028.   int outsize = 0;
  1029.   int createmode;
  1030.   mode_t unixmode;
  1031.   
  1032.   cnum = SVAL(inbuf,smb_tid);
  1033.   createmode = SVAL(inbuf,smb_vwv0);
  1034.   sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
  1035.   unix_convert(fname,cnum);
  1036.   
  1037.   unixmode = unix_mode(cnum,createmode);
  1038.   
  1039.   fnum = find_free_file();
  1040.   if (fnum < 0)
  1041.     return(ERROR(ERRSRV,ERRnofids));
  1042.  
  1043.   if (!check_name(fname,cnum))
  1044.     return(ERROR(ERRDOS,ERRnoaccess));
  1045.  
  1046.   strcpy(fname2,(char *)mktemp(fname));
  1047.  
  1048.   open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode);
  1049.  
  1050.   if (!Files[fnum].open)
  1051.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1052.  
  1053.   outsize = set_message(outbuf,1,2 + strlen(fname2),True);
  1054.   SSVAL(outbuf,smb_vwv0,fnum);
  1055.   CVAL(smb_buf(outbuf),0) = 4;
  1056.   strcpy(smb_buf(outbuf) + 1,fname2);
  1057.   
  1058.   DEBUG(2,("created temp file %s\n",fname2));
  1059.   DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd,fnum,cnum,createmode,unixmode));
  1060.   
  1061.   return(outsize);
  1062. }
  1063.  
  1064.  
  1065. /****************************************************************************
  1066.   reply to a unlink
  1067. ****************************************************************************/
  1068. int reply_unlink(char *inbuf,char *outbuf)
  1069. {
  1070.   int outsize = 0;
  1071.   pstring name="";
  1072.   BOOL isrootdir;
  1073.   int cnum;
  1074.   int dirtype;
  1075.   pstring directory="";
  1076.   pstring mask="";
  1077.   char *p;
  1078.   int count=0;
  1079.   int error = ERRnoaccess;
  1080.   BOOL rm_file;
  1081.   BOOL ok = False;
  1082.   
  1083.   cnum = SVAL(inbuf,smb_tid);
  1084.  
  1085.   dirtype = SVAL(inbuf,smb_vwv0);
  1086.   
  1087.   strcpy(name,smb_buf(inbuf) + 1);
  1088.    
  1089.   DEBUG(3,("reply_unlink : %s\n",name));
  1090.    
  1091.   unix_convert(name,cnum);
  1092.  
  1093.   p = strrchr(name,'/');
  1094.   if (!p)
  1095.     {
  1096.       strcpy(directory,"./");
  1097.       strcpy(mask,name);
  1098.     }
  1099.   else
  1100.     {
  1101.       *p = 0;
  1102.       strcpy(directory,name);
  1103.       strcpy(mask,p+1);
  1104.     }
  1105.  
  1106.   isrootdir = (strequal(directory,"./") ||
  1107.            strequal(directory,"."));
  1108.   
  1109.   
  1110.   {
  1111.     void *dirptr = NULL;
  1112.     struct DIRECT *dptr;
  1113.  
  1114.     if (check_name(directory,cnum))
  1115.       dirptr = (void *)opendir(directory);
  1116.  
  1117.     if (dirptr)
  1118.       {
  1119.     BOOL has_wild = (strchr(mask,'?') || strchr(mask,'*'));
  1120.     BOOL do_mangling;
  1121.  
  1122.     ok = True;
  1123.     error = ERRbadfile;
  1124.     
  1125.     while ((dptr = readdir(dirptr)))
  1126.       {
  1127.         pstring fname="";
  1128.         int fmode;
  1129.         rm_file = False; /* Set to true if we want to delete this file */
  1130.         
  1131.         strcpy(fname,dptr->d_name);
  1132.  
  1133.         do_mangling = ((has_wild || strchr(mask,magic_char)) && 
  1134.                lp_manglednames(SNUM(cnum)));
  1135.         
  1136.         /* We need to check the wildcard in different ways depending on
  1137.            whether long_filenames are needed in use. */
  1138.  
  1139.         if(!long_filenames)
  1140.           {
  1141.         if ((strcmp(fname,mask) == 0) ||
  1142.             (name_convert(fname,dptr->d_name,
  1143.                   do_mangling,
  1144.                   lp_mangled_map(SNUM(cnum))) &&
  1145.              mask_match(fname,mask,!isrootdir,False,False)))
  1146.           rm_file = True;
  1147.           }
  1148.         else /* Do Lanman2 wildcard matching */
  1149.           {
  1150.         if(lanman2_match(fname, mask, casesignames))
  1151.           rm_file = True;
  1152.           }
  1153.  
  1154.         if(rm_file)
  1155.           {
  1156.         struct stat sbuf;
  1157.         error = ERRnoaccess;
  1158.         sprintf(fname,"%s/%s",directory,dptr->d_name);
  1159.         if (stat(fname,&sbuf) != 0) continue;
  1160.         fmode = dos_mode(cnum,fname,&sbuf);
  1161.         if ((fmode & aDIR) != 0) continue;
  1162.         if ((fmode & aRONLY) != 0) continue;
  1163.         if (((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) != 0)
  1164.           continue;          
  1165.         unlink(fname);
  1166.         DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
  1167.         count++;
  1168.           }        
  1169.       }
  1170.     closedir(dirptr);
  1171.       }
  1172.   }
  1173.   
  1174.   if (!ok || count == 0)
  1175.     return(ERROR(ERRDOS,error));
  1176.   
  1177.   outsize = set_message(outbuf,0,0,True);
  1178.   
  1179.   return(outsize);
  1180. }
  1181.  
  1182.  
  1183. /****************************************************************************
  1184.    reply to a readbraw (core+ protocol)
  1185. ****************************************************************************/
  1186. int reply_readbraw(char *inbuf, char *outbuf)
  1187. {
  1188.   extern int Client;
  1189.   int cnum,maxcount,mincount,timeout,fnum;
  1190.   BOOL nonblocking = False;
  1191.   int nread = 0;
  1192.   int ret=0, nwritten;
  1193.   int startpos;
  1194.   static char *read_buf=NULL;
  1195.   static int read_buf_size=0;
  1196.  
  1197.   cnum = SVAL(inbuf,smb_tid);
  1198.   fnum = GETFNUM(inbuf,smb_vwv0);
  1199.   if (!OPEN_FNUM(fnum))
  1200.     return(ERROR(ERRDOS,ERRbadfid));
  1201.  
  1202.   startpos = IVAL(inbuf,smb_vwv1);
  1203.   maxcount = SVAL(inbuf,smb_vwv3);
  1204.   mincount = SVAL(inbuf,smb_vwv4);
  1205.   timeout = IVALS(inbuf,smb_vwv5);
  1206.   if(timeout == 0)
  1207.     nonblocking = True;
  1208.  
  1209.   /* ensure we don't overrun the packet size */
  1210.   maxcount = MIN(65535,maxcount);
  1211.   maxcount = MAX(mincount,maxcount);
  1212.  
  1213.   if (!read_buf || read_buf_size < maxcount+8)    
  1214.     {
  1215.       DEBUG(5,("expanding read_buf\n"));
  1216.       read_buf = (char *)Realloc(read_buf,maxcount+8);
  1217.       read_buf_size = maxcount+8;
  1218.     }
  1219.  
  1220.   if (!read_buf)
  1221.     DEBUG(0,("Out of memory in readbraw!\n"));
  1222.   
  1223.     {
  1224.       int toread = maxcount;
  1225.  
  1226.       if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1227.     {
  1228.       if (!is_locked(fnum,cnum,toread,startpos))
  1229.         {
  1230.           nread = 0;
  1231.  
  1232.           if (toread > 0)
  1233.         {
  1234.           /* NOTE: We are ignoring mincount! */
  1235.           nread += read_file(fnum,
  1236.                      &read_buf[4+nread],
  1237.                      startpos+nread,
  1238.                      toread, toread,
  1239.                      (long)timeout,
  1240.                      True);
  1241.         }
  1242.         }
  1243.     }
  1244.     }
  1245.   
  1246.   DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d timeout=%d nread=%d\n",
  1247.     timestring(),
  1248.     fnum,cnum,startpos,
  1249.     maxcount,mincount,timeout,nread));
  1250.   
  1251.   if (nread < 0)
  1252.     nread = 0; /* X/Open says not to return an error - just send a 0 
  1253.           buffer back */
  1254.   
  1255.   /* Set up a return message and send it directly to the SMB redirector.
  1256.      Return -1 to signal no reply should be sent */
  1257.   /* Set up the Netbios message header */
  1258.   CVAL(read_buf,0) = 0;
  1259.   CVAL(read_buf,1) = 0;
  1260.  
  1261.   SSVAL(read_buf,2,nread);
  1262.   BSWP(read_buf+2,2); 
  1263.  
  1264.   nread += 4; /* Include header */
  1265.   nwritten = 0;
  1266.  
  1267.   log_out(read_buf,nread);
  1268.  
  1269.   while (nwritten < nread)
  1270.     {
  1271.       ret = write_socket(Client,read_buf+nwritten,nread - nwritten);
  1272.       if (ret <= 0)
  1273.     {
  1274.       DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",nread-nwritten,ret));
  1275.       close_sockets();
  1276.       exit_server();
  1277.     }
  1278.       nwritten += ret;
  1279.     }
  1280.  
  1281.   DEBUG(5,("readbraw finished\n"));
  1282.   return -1;
  1283. }
  1284.  
  1285.  
  1286. /****************************************************************************
  1287.   reply to a lockread (core+ protocol)
  1288. ****************************************************************************/
  1289. int reply_lockread(char *inbuf,char *outbuf,int length,int bufsize)
  1290. {
  1291.   int cnum,fnum;
  1292.   int nread = -1;
  1293.   char *data;
  1294.   int outsize = 0;
  1295.   uint32 startpos, numtoread;
  1296.   int eclass;
  1297.   uint32 ecode;
  1298.   BOOL ok = False;
  1299.   
  1300.   cnum = SVAL(inbuf,smb_tid);
  1301.   fnum = GETFNUM(inbuf,smb_vwv0);
  1302.   if (!OPEN_FNUM(fnum))
  1303.     return(ERROR(ERRDOS,ERRbadfid));
  1304.   if (Protocol >= PROTOCOL_LANMAN1)
  1305.     {
  1306.       if(HAS_CACHED_ERROR(fnum))
  1307.     return (CACHED_ERROR(fnum));
  1308.     }
  1309.   numtoread = SVAL(inbuf,smb_vwv1);
  1310.   startpos = IVAL(inbuf,smb_vwv2);
  1311.   
  1312.   outsize = set_message(outbuf,5,3,True);
  1313.   numtoread = MIN(bufsize-outsize,numtoread);
  1314.   data = smb_buf(outbuf) + 3;
  1315.   
  1316.     {
  1317.       if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1318.     {
  1319.       if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
  1320.         {
  1321.           return (ERROR(eclass,ecode));
  1322.         }
  1323.       nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False);
  1324.       ok = True;      
  1325.     }
  1326.     }
  1327.   
  1328.   if ((nread < 0) || !ok)
  1329.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1330.   
  1331.   outsize += nread;
  1332.   SSVAL(outbuf,smb_vwv0,nread);
  1333.   SSVAL(outbuf,smb_vwv5,nread+3);
  1334.   SSVAL(smb_buf(outbuf),1,nread);
  1335.   
  1336.   DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
  1337.   
  1338.   return(outsize);
  1339. }
  1340.  
  1341.  
  1342. /****************************************************************************
  1343.   reply to a read
  1344. ****************************************************************************/
  1345. int reply_read(char *inbuf,char *outbuf,int length,int bufsize)
  1346. {
  1347.   int cnum,numtoread,fnum;
  1348.   int nread = -1;
  1349.   char *data;
  1350.   int startpos;
  1351.   int outsize = 0;
  1352.   BOOL ok = False;
  1353.   
  1354.   cnum = SVAL(inbuf,smb_tid);
  1355.   fnum = GETFNUM(inbuf,smb_vwv0);
  1356.   if (!OPEN_FNUM(fnum))
  1357.     return(ERROR(ERRDOS,ERRbadfid));
  1358.   if (Protocol >= PROTOCOL_LANMAN1)
  1359.     {
  1360.       if(HAS_CACHED_ERROR(fnum))
  1361.     return (CACHED_ERROR(fnum));
  1362.     }
  1363.   numtoread = SVAL(inbuf,smb_vwv1);
  1364.   startpos = IVAL(inbuf,smb_vwv2);
  1365.   
  1366.   outsize = set_message(outbuf,5,3,True);
  1367.   numtoread = MIN(bufsize-outsize,numtoread);
  1368.   data = smb_buf(outbuf) + 3;
  1369.   
  1370.   {
  1371.     if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1372.       {
  1373.     if (is_locked(fnum,cnum,numtoread,startpos))
  1374.       return(ERROR(ERRDOS,ERRlock));
  1375.     
  1376.     nread = 0;
  1377.  
  1378.     if (numtoread > 0)
  1379.       {
  1380.         nread += read_file(fnum,data,
  1381.                    startpos,
  1382.                    numtoread,
  1383.                    numtoread,
  1384.                    -1,
  1385.                    False);
  1386.       }
  1387.     ok = (nread >= 0);
  1388.       }
  1389.   }
  1390.   
  1391.   
  1392.   if ((nread < 0) || !ok)
  1393.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1394.   
  1395.   outsize += nread;
  1396.   SSVAL(outbuf,smb_vwv0,nread);
  1397.   SSVAL(outbuf,smb_vwv5,nread+3);
  1398.   SSVAL(smb_buf(outbuf),1,nread);
  1399.   
  1400.   DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
  1401.   
  1402.   return(outsize);
  1403. }
  1404.  
  1405.  
  1406. /****************************************************************************
  1407.   reply to a read and X
  1408. ****************************************************************************/
  1409. int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
  1410. {
  1411.   int smb_com2 = CVAL(inbuf,smb_vwv0);
  1412.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  1413.   int smb_fid = GETFNUM(inbuf,smb_vwv2);
  1414.   uint32 smb_offset = IVAL(inbuf,smb_vwv3);
  1415.   int smb_maxcnt = SVAL(inbuf,smb_vwv5);
  1416.   int smb_mincnt = SVAL(inbuf,smb_vwv6);
  1417. #if 0
  1418.   uint32 smb_timeout = SVAL(inbuf,smb_vwv7);
  1419. #endif
  1420.   int cnum;
  1421.   int nread = -1;
  1422.   char *data;
  1423.   int outsize = 0;
  1424.   BOOL ok = False;
  1425.  
  1426.   cnum = SVAL(inbuf,smb_tid);
  1427.  
  1428.   if (Protocol >= PROTOCOL_LANMAN1)
  1429.     {
  1430.       if(HAS_CACHED_ERROR(smb_fid))
  1431.     return (CACHED_ERROR(smb_fid));
  1432.     }
  1433.   outsize = set_message(outbuf,12,0,True);
  1434.   data = smb_buf(outbuf);
  1435.   
  1436.     {
  1437.       if (OPEN_FNUM(smb_fid) && (Files[smb_fid].cnum == cnum))
  1438.     {
  1439.       if (is_locked(smb_fid,cnum,smb_maxcnt,smb_offset))
  1440.         return(ERROR(ERRDOS,ERRlock));
  1441.       nread = read_file(smb_fid,data,smb_offset,smb_maxcnt,smb_maxcnt,-1,False);
  1442.       ok = True;
  1443.     }
  1444.     }
  1445.   
  1446.   
  1447.   if ((nread < 0) || !ok)
  1448.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1449.   
  1450.   outsize += nread;
  1451.   CVAL(outbuf,smb_vwv0) = smb_com2;
  1452.   SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
  1453.   SSVAL(outbuf,smb_vwv5,nread);
  1454.   SSVAL(outbuf,smb_vwv6,(int)(data - ((outbuf-chain_size)+4)));
  1455.   SSVAL(smb_buf(outbuf),-2,nread);
  1456.   
  1457.   DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d com2=%d off2=%d\n",
  1458.     timestring(),smb_fid,cnum,
  1459.     smb_mincnt,smb_maxcnt,nread,smb_com2,smb_off2));
  1460.  
  1461.   chain_fnum = smb_fid;
  1462.  
  1463.   if (smb_com2 != 0xFF)
  1464.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  1465.                outbuf,outbuf+outsize,
  1466.                length,bufsize);
  1467.   
  1468.   chain_fnum = -1;
  1469.   
  1470.   return(outsize);
  1471. }
  1472.  
  1473.  
  1474. /****************************************************************************
  1475.   reply to a writebraw (core+ or LANMAN1.0 protocol)
  1476. ****************************************************************************/
  1477. int reply_writebraw(char *inbuf,char *outbuf)
  1478. {
  1479.   int nwritten=0;
  1480.   int total_written=0;
  1481.   int numtowrite=0;
  1482.   int cnum,fnum;
  1483.   int outsize = 0;
  1484.   long startpos, timeout;
  1485.   char *read_buf=NULL;
  1486.   char *data=NULL;
  1487.   BOOL ok = False;
  1488.   BOOL write_through;
  1489.   
  1490.   cnum = SVAL(inbuf,smb_tid);
  1491.   fnum = GETFNUM(inbuf,smb_vwv0);
  1492.  
  1493.   if (!OPEN_FNUM(fnum))
  1494.     return(ERROR(ERRDOS,ERRbadfid));
  1495.  
  1496.   if (Files[fnum].read_only)
  1497.     return(ERROR(ERRSRV,ERRaccess));
  1498.   
  1499.   if (Protocol >= PROTOCOL_LANMAN1)
  1500.     {
  1501.       if(HAS_CACHED_ERROR(fnum))
  1502.     return(CACHED_ERROR(fnum));
  1503.     }
  1504.  
  1505.   startpos = IVAL(inbuf,smb_vwv3);
  1506.   timeout = IVALS(inbuf,smb_vwv5);
  1507.   write_through = ((SVAL(inbuf,smb_vwv7) & 1) != 0);
  1508.  
  1509.   /* We have to deal with slightly different formats depending
  1510.      on whether we are using the core+ or lanman1.0 protocol */
  1511.   if(Protocol == PROTOCOL_COREPLUS) {
  1512.     numtowrite = SVAL(smb_buf(inbuf),-2);
  1513.     /* NB there is no length field here */
  1514.     data = smb_buf(inbuf);
  1515.   } else { /* LANMAN1.0 Protocol */
  1516.     numtowrite = SVAL(inbuf,smb_vwv10);
  1517.     data = inbuf + 4 + SVAL(inbuf, smb_vwv11);
  1518.   }
  1519.   
  1520.     {
  1521.       extern int Client;
  1522.       if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1523.     {
  1524.       if (is_locked(fnum,cnum,numtowrite,startpos))
  1525.         return(ERROR(ERRDOS,ERRlock));
  1526.  
  1527.       if (seek_file(fnum,startpos) != startpos)
  1528.         DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
  1529.  
  1530.       if (numtowrite>0)
  1531.         nwritten = write_with_timeout(Files[fnum].fd,
  1532.                       data,numtowrite,
  1533.                       timeout);
  1534. #ifndef NO_FSYNC
  1535.       if(write_through)
  1536.         fsync(Files[fnum].fd);
  1537. #endif
  1538.  
  1539.       ok = True;
  1540.   
  1541.       DEBUG(3,("%s writebraw message 1 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
  1542.         timestring(),fnum,cnum,startpos,numtowrite,nwritten));
  1543.       DEBUG(5,("writethrough=%d\n",write_through));
  1544.  
  1545.       if ((nwritten < numtowrite) || !ok) 
  1546.         return(UNIXERROR(ERRDOS,ERRnoaccess));
  1547.  
  1548.       total_written = nwritten;
  1549.  
  1550.       /* Return a message to the redirector to tell it
  1551.          to send more bytes */
  1552.       CVAL(outbuf,smb_com) = SMBwritebraw;
  1553.  
  1554.       if(Protocol <= PROTOCOL_COREPLUS) {
  1555.         outsize = set_message(outbuf,0,0,True);
  1556.       } else { /* LANMAN1.0 Protocol */
  1557.         outsize = set_message(outbuf,1,0,True);
  1558.         SSVALS(outbuf,smb_vwv0,-1);  /* We don't support smb_remaining */
  1559.       }
  1560.       smb_setlen(outbuf, outsize-4);
  1561.       send_smb(outbuf);
  1562.  
  1563.       /* Now read the raw data into the buffer and write it */
  1564.       if(read_smb_length(Client,inbuf,0) == -1) {
  1565.         DEBUG(0,("Failed to read length of secondary writebraw\n"));
  1566.         close_sockets();
  1567.         exit_server();
  1568.       }
  1569.  
  1570.       /* Even though this is not an smb message, smb_len
  1571.          returns the generic length of an smb message */
  1572.       numtowrite = smb_len(inbuf);
  1573.       if (numtowrite > 0)
  1574.         {
  1575.           read_buf = (char *)malloc(numtowrite + SAFETY_MARGIN);
  1576.           if (!read_buf)
  1577.         DEBUG(0,("Out of memory in writebraw!\n"));
  1578.  
  1579.           if(!read_data(Client,read_buf,numtowrite)) {
  1580.         DEBUG(0,("Failed to read data in secondary writebraw\n"));
  1581.         close_sockets();
  1582.         exit_server();
  1583.           }
  1584.  
  1585.  
  1586.           if (is_locked(fnum,cnum,numtowrite,startpos + total_written))
  1587.         return(ERROR(ERRDOS,ERRlock));
  1588.  
  1589.           nwritten = write_with_timeout(Files[fnum].fd,
  1590.                         read_buf,numtowrite,
  1591.                         timeout);
  1592.           if (read_buf) free(read_buf);
  1593.  
  1594.           total_written += nwritten;
  1595.         }
  1596.  
  1597. #ifndef NO_FSYNC
  1598.       if(write_through)
  1599.         fsync(Files[fnum].fd);
  1600. #endif
  1601.       DEBUG(5,("writethrough=%d\n",write_through));
  1602.  
  1603.       ok = True;
  1604.  
  1605.       /* Set up outbuf to return the correct return */
  1606.       outsize = set_message(outbuf,1,0,True);
  1607.       CVAL(outbuf,smb_com) = SMBwritec;
  1608.       SSVAL(outbuf,smb_vwv0,total_written);
  1609.     }
  1610.     }
  1611.  
  1612.   DEBUG(3,("%s writebraw extra fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
  1613.         timestring(),fnum,cnum,startpos,numtowrite,total_written));
  1614.  
  1615.   return(outsize);
  1616. }
  1617.  
  1618.  
  1619. /****************************************************************************
  1620.   reply to a writeunlock (core+)
  1621. ****************************************************************************/
  1622. int reply_writeunlock(char *inbuf,char *outbuf)
  1623. {
  1624.   int cnum,fnum;
  1625.   int nwritten = -1;
  1626.   int outsize = 0;
  1627.   int fd;
  1628.   char *data;
  1629.   uint32 numtowrite,startpos;
  1630.   int eclass;
  1631.   uint32 ecode;
  1632.   BOOL ok = False;
  1633.   
  1634.   cnum = SVAL(inbuf,smb_tid);
  1635.   fnum = GETFNUM(inbuf,smb_vwv0);
  1636.   if (!OPEN_FNUM(fnum))
  1637.     return(ERROR(ERRDOS,ERRbadfid));
  1638.  
  1639.   if (Files[fnum].read_only)
  1640.     return(ERROR(ERRSRV,ERRaccess));
  1641.  
  1642.   if (Protocol >= PROTOCOL_LANMAN1)
  1643.     {
  1644.       if(HAS_CACHED_ERROR(fnum))
  1645.     return (CACHED_ERROR(fnum));
  1646.     }  
  1647.   numtowrite = SVAL(inbuf,smb_vwv1);
  1648.   startpos = IVAL(inbuf,smb_vwv2);
  1649.   data = smb_buf(inbuf) + 3;
  1650.   
  1651.   fd = Files[fnum].fd;
  1652.  
  1653.   if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1654.     {
  1655.       if (is_locked(fnum,cnum,numtowrite,startpos))
  1656.     return(ERROR(ERRDOS,ERRlock));
  1657.  
  1658.       seek_file(fnum,startpos);
  1659.  
  1660.       /* The special X/Open SMB protocol handling of
  1661.      zero length writes is *NOT* done for
  1662.      this call */
  1663.       if(numtowrite == 0)
  1664.     nwritten = 0;
  1665.       else
  1666.     nwritten = write(fd,data,numtowrite);
  1667.       ok = True;
  1668.     }
  1669.   
  1670.   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0) || !ok)
  1671.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1672.  
  1673.   if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
  1674.     return(ERROR(eclass,ecode));
  1675.  
  1676.   outsize = set_message(outbuf,1,0,True);
  1677.   
  1678.   SSVAL(outbuf,smb_vwv0,nwritten);
  1679.   
  1680.   DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
  1681.   
  1682.   return(outsize);
  1683. }
  1684.  
  1685.  
  1686. /****************************************************************************
  1687.   reply to a write
  1688. ****************************************************************************/
  1689. int reply_write(char *inbuf,char *outbuf)
  1690. {
  1691.   int cnum,numtowrite,fnum;
  1692.   int nwritten = -1;
  1693.   int outsize = 0;
  1694.   int startpos;
  1695.   int fd;
  1696.   char *data;
  1697.   BOOL ok = False;
  1698.   
  1699.   cnum = SVAL(inbuf,smb_tid);
  1700.   fnum = GETFNUM(inbuf,smb_vwv0);
  1701.  
  1702.   if (!OPEN_FNUM(fnum))
  1703.     return(ERROR(ERRDOS,ERRbadfid));
  1704.  
  1705.   if (Files[fnum].read_only)
  1706.     return(ERROR(ERRSRV,ERRaccess));
  1707.  
  1708.   if (Protocol >= PROTOCOL_LANMAN1)
  1709.     {
  1710.       if(HAS_CACHED_ERROR(fnum))
  1711.     return (CACHED_ERROR(fnum));
  1712.     }  
  1713.   numtowrite = SVAL(inbuf,smb_vwv1);
  1714.   startpos = IVAL(inbuf,smb_vwv2);
  1715.   data = smb_buf(inbuf) + 3;
  1716.   
  1717.   fd = Files[fnum].fd;
  1718.  
  1719.   if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1720.     {
  1721.       if (is_locked(fnum,cnum,numtowrite,startpos))
  1722.     return(ERROR(ERRDOS,ERRlock));
  1723.  
  1724.       seek_file(fnum,startpos);
  1725.  
  1726.       /* X/Open SMB protocol says that if smb_vwv1 is
  1727.      zero then the file size should be extended or
  1728.      truncated to the size given in smb_vwv[2-3] */
  1729.       if(numtowrite == 0)
  1730.     nwritten = set_filelen(fd, startpos);
  1731.       else
  1732.     nwritten = write(fd,data,numtowrite);
  1733.       ok = True;
  1734.     }
  1735.   
  1736.   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0) || !ok)
  1737.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1738.  
  1739.   outsize = set_message(outbuf,1,0,True);
  1740.   
  1741.   SSVAL(outbuf,smb_vwv0,nwritten);
  1742.   
  1743.   DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
  1744.   
  1745.   return(outsize);
  1746. }
  1747.  
  1748.  
  1749. /****************************************************************************
  1750.   reply to a write and X
  1751. ****************************************************************************/
  1752. int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
  1753. {
  1754.   int smb_com2 = CVAL(inbuf,smb_vwv0);
  1755.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  1756.   int fnum = GETFNUM(inbuf,smb_vwv2);
  1757.   uint32 smb_offset = IVAL(inbuf,smb_vwv3);
  1758.   int smb_dsize = SVAL(inbuf,smb_vwv10);
  1759.   int smb_doff = SVAL(inbuf,smb_vwv11);
  1760.  
  1761.   int cnum;
  1762.   int nwritten = -1;
  1763.   int outsize = 0;
  1764.   int fd;
  1765.   char *data;
  1766.   BOOL ok = False;
  1767.   
  1768.   cnum = SVAL(inbuf,smb_tid);
  1769.  
  1770.   if (!OPEN_FNUM(fnum))
  1771.     return(ERROR(ERRDOS,ERRbadfid));
  1772.  
  1773.   if (Files[fnum].read_only)
  1774.     return(ERROR(ERRSRV,ERRaccess));
  1775.  
  1776.   if (Protocol >= PROTOCOL_LANMAN1)
  1777.     {
  1778.       if(HAS_CACHED_ERROR(fnum))
  1779.     return (CACHED_ERROR(fnum));
  1780.     }
  1781.  
  1782.   data = inbuf + 4 + smb_doff;
  1783.   
  1784.   fd = Files[fnum].fd;
  1785.  
  1786.   if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1787.     {
  1788.       if (is_locked(fnum,cnum,smb_dsize,smb_offset))
  1789.     return(ERROR(ERRDOS,ERRlock));
  1790.  
  1791.       seek_file(fnum,smb_offset);
  1792.  
  1793.       /* X/Open SMB protocol says that, unlike SMBwrite
  1794.      if the length is zero then NO truncation is
  1795.      done, just a write of zero. To truncate a file,
  1796.      use SMBwrite. */
  1797.       if(smb_dsize == 0)
  1798.     nwritten = 0;
  1799.       else
  1800.     nwritten = write(fd,data,smb_dsize);
  1801.       ok = True;
  1802.     }
  1803.   
  1804.   if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0) || !ok)
  1805.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1806.  
  1807.   outsize = set_message(outbuf,6,0,True);
  1808.   
  1809.   CVAL(outbuf,smb_vwv0) = smb_com2;
  1810.   SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
  1811.   SSVAL(outbuf,smb_vwv2,nwritten);
  1812.   
  1813.   DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
  1814.  
  1815.   chain_fnum = fnum;
  1816.  
  1817.   if (smb_com2 != 0xFF)
  1818.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  1819.                outbuf,outbuf+outsize,
  1820.                length,bufsize);
  1821.   
  1822.   chain_fnum = -1;
  1823.   
  1824.   return(outsize);
  1825. }
  1826.  
  1827.  
  1828. /****************************************************************************
  1829.   reply to a lseek
  1830. ****************************************************************************/
  1831. int reply_lseek(char *inbuf,char *outbuf)
  1832. {
  1833.   int cnum,fnum;
  1834.   uint32 startpos;
  1835.   int32 res=-1;
  1836.   int mode;
  1837.   int outsize = 0;
  1838.   BOOL ok = False;
  1839.   
  1840.   cnum = SVAL(inbuf,smb_tid);
  1841.   fnum = GETFNUM(inbuf,smb_vwv0);
  1842.   if (!OPEN_FNUM(fnum))
  1843.     return(ERROR(ERRDOS,ERRbadfid));
  1844.   if (Protocol >= PROTOCOL_LANMAN1)
  1845.     {
  1846.       if(HAS_CACHED_ERROR(fnum))
  1847.     return (CACHED_ERROR(fnum));
  1848.     }
  1849.   mode = SVAL(inbuf,smb_vwv1);
  1850.   startpos = IVAL(inbuf,smb_vwv2);
  1851.   
  1852.     {
  1853.       if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1854.     {
  1855.       res = lseek(Files[fnum].fd,startpos,mode);
  1856.       Files[fnum].pos = -1;
  1857.     }
  1858.       ok = True;
  1859.     }
  1860.   
  1861.   
  1862.   if ((res < 0) || !ok)
  1863.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1864.   
  1865.   outsize = set_message(outbuf,2,0,True);
  1866.   SIVAL(outbuf,smb_vwv0,res);
  1867.   
  1868.   DEBUG(3,("%s lseek fnum=%d cnum=%d pos=%d\n",timestring(),fnum,cnum,startpos));
  1869.   
  1870.   return(outsize);
  1871. }
  1872.  
  1873.  
  1874. /****************************************************************************
  1875.   reply to a flush
  1876. ****************************************************************************/
  1877. int reply_flush(char *inbuf,char *outbuf)
  1878. {
  1879.   int cnum, fnum;
  1880.   int outsize = set_message(outbuf,0,0,True);
  1881.  
  1882.   cnum = SVAL(inbuf,smb_tid);
  1883.   fnum = GETFNUM(inbuf,smb_vwv0);
  1884.   if (Protocol >= PROTOCOL_LANMAN1 && OPEN_FNUM(fnum))
  1885.     {
  1886.       if(HAS_CACHED_ERROR(fnum))
  1887.     return (CACHED_ERROR(fnum));
  1888.     }
  1889.  
  1890. #ifndef NO_FSYNC
  1891.   if (fnum == 0xFFFF)
  1892.     {
  1893.       int i;
  1894.       for (i=0;i<MAX_OPEN_FILES;i++)
  1895.     if (OPEN_FNUM(i))
  1896.       fsync(Files[i].fd);
  1897.     }
  1898.   else
  1899.     {
  1900.       if (OPEN_FNUM(fnum))
  1901.     fsync(Files[fnum].fd);
  1902.     }
  1903. #endif
  1904.  
  1905.   DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
  1906.   return(outsize);
  1907. }
  1908.  
  1909.  
  1910. /****************************************************************************
  1911.   reply to a exit
  1912. ****************************************************************************/
  1913. int reply_exit(char *inbuf,char *outbuf)
  1914. {
  1915.   int outsize = set_message(outbuf,0,0,True);
  1916.   DEBUG(3,("%s exit\n",timestring()));
  1917.   
  1918.   return(outsize);
  1919. }
  1920.  
  1921.  
  1922. /****************************************************************************
  1923.   reply to a close
  1924. ****************************************************************************/
  1925. int reply_close(char *inbuf,char *outbuf)
  1926. {
  1927.   int fnum,cnum;
  1928.   int outsize = 0;
  1929.   BOOL ok = False;  
  1930.   time_t mtime;
  1931.   int32 eclass = 0, err = 0;
  1932.  
  1933.   outsize = set_message(outbuf,0,0,True);
  1934.  
  1935.   cnum = SVAL(inbuf,smb_tid);
  1936.  
  1937.   fnum = GETFNUM(inbuf,smb_vwv0);
  1938.   if (!OPEN_FNUM(fnum))
  1939.     return(ERROR(ERRDOS,ERRbadfid));
  1940.  
  1941.   if (Protocol >= PROTOCOL_LANMAN1)
  1942.     {
  1943.       /* Make sure we have done the close first */
  1944.       if(HAS_CACHED_ERROR(fnum))
  1945.     {
  1946.       eclass = Files[fnum].wbmpx_ptr->wr_errclass;
  1947.       err = Files[fnum].wbmpx_ptr->wr_error;
  1948.     }
  1949.     }
  1950.   mtime = IVAL(inbuf,smb_vwv1);
  1951.  
  1952.     {
  1953.       if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1954.     {
  1955.       close_file(fnum);
  1956.  
  1957.       /* try and set the date */
  1958.       if (mtime == 0 || mtime == -1)
  1959.         DEBUG(5,("not setting null date\n"));
  1960.       else
  1961.         set_filetime(Files[fnum].name,mtime + LOCAL_TO_GMT * TimeDiff());
  1962.  
  1963.       ok = True;
  1964.     }
  1965.     }
  1966.  
  1967.   /* We have a cached error */
  1968.   if(eclass || err)
  1969.     return(ERROR(eclass,err));
  1970.  
  1971.   if (!ok)
  1972.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1973.   
  1974.  
  1975.   DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
  1976.     timestring(),Files[fnum].fd,fnum,cnum,num_files_open));
  1977.   
  1978.   return(outsize);
  1979. }
  1980.  
  1981.  
  1982. /****************************************************************************
  1983.   reply to a writeclose (Core+ protocol)
  1984. ****************************************************************************/
  1985. int reply_writeclose(char *inbuf,char *outbuf)
  1986. {
  1987.   int cnum,numtowrite,fnum;
  1988.   int nwritten = -1;
  1989.   int outsize = 0;
  1990.   int startpos;
  1991.   char *data;
  1992.   time_t mtime;
  1993.   BOOL ok = False;
  1994.   
  1995.   cnum = SVAL(inbuf,smb_tid);
  1996.   fnum = GETFNUM(inbuf,smb_vwv0);
  1997.  
  1998.   if (!OPEN_FNUM(fnum))
  1999.     return(ERROR(ERRDOS,ERRbadfid));
  2000.  
  2001.   if (Files[fnum].read_only)
  2002.     return(ERROR(ERRSRV,ERRaccess));
  2003.   
  2004.   if (Protocol >= PROTOCOL_LANMAN1)
  2005.     {
  2006.       if(HAS_CACHED_ERROR(fnum))
  2007.     return (CACHED_ERROR(fnum));
  2008.     }
  2009.   numtowrite = SVAL(inbuf,smb_vwv1);
  2010.   startpos = IVAL(inbuf,smb_vwv2);
  2011.   mtime = IVAL(inbuf,smb_vwv4);
  2012.   data = smb_buf(inbuf) + 1;
  2013.   
  2014.   if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  2015.     {
  2016.       if (is_locked(fnum,cnum,numtowrite,startpos))
  2017.     return(ERROR(ERRDOS,ERRlock));
  2018.       
  2019.       seek_file(fnum,startpos);
  2020.       
  2021.       nwritten = write(Files[fnum].fd,data,numtowrite);
  2022.       ok = True;
  2023.       
  2024.       close_file(fnum);
  2025.  
  2026.       if (mtime == 0 || mtime == -1)
  2027.     DEBUG(5,("not setting null date\n"));
  2028.       else
  2029.     set_filetime(Files[fnum].name,mtime + LOCAL_TO_GMT * TimeDiff());
  2030.     }
  2031.   
  2032.   DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
  2033.     timestring(),fnum,cnum,numtowrite,nwritten,num_files_open));
  2034.   
  2035.   if ((nwritten <= 0) || !ok)
  2036.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2037.   
  2038.   outsize = set_message(outbuf,1,0,True);
  2039.   
  2040.   SSVAL(outbuf,smb_vwv0,nwritten);
  2041.   return(outsize);
  2042. }
  2043.  
  2044.  
  2045. /****************************************************************************
  2046.   reply to a lock
  2047. ****************************************************************************/
  2048. int reply_lock(char *inbuf,char *outbuf)
  2049. {
  2050.   int fnum,cnum;
  2051.   int outsize = set_message(outbuf,0,0,True);
  2052.   uint32 count,offset;
  2053.   int eclass;
  2054.   uint32 ecode;
  2055.  
  2056.   cnum = SVAL(inbuf,smb_tid);
  2057.   fnum = GETFNUM(inbuf,smb_vwv0);
  2058.   if (!OPEN_FNUM(fnum))
  2059.     return(ERROR(ERRDOS,ERRbadfid));
  2060.   if (Protocol >= PROTOCOL_LANMAN1)
  2061.     {
  2062.       if(HAS_CACHED_ERROR(fnum))
  2063.     return (CACHED_ERROR(fnum));
  2064.     }
  2065.  
  2066.   count = IVAL(inbuf,smb_vwv1);
  2067.   offset = IVAL(inbuf,smb_vwv3);
  2068.  
  2069.   DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
  2070.  
  2071.   if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
  2072.     return (ERROR(eclass,ecode));
  2073.   
  2074.   return(outsize);
  2075. }
  2076.  
  2077.  
  2078. /****************************************************************************
  2079.   reply to a unlock
  2080. ****************************************************************************/
  2081. int reply_unlock(char *inbuf,char *outbuf)
  2082. {
  2083.   int fnum,cnum;
  2084.   int outsize = set_message(outbuf,0,0,True);
  2085.   uint32 count,offset;
  2086.   int eclass;
  2087.   uint32 ecode;
  2088.   
  2089.   cnum = SVAL(inbuf,smb_tid);
  2090.   fnum = GETFNUM(inbuf,smb_vwv0);
  2091.   if (!OPEN_FNUM(fnum))
  2092.     return(ERROR(ERRDOS,ERRbadfid));
  2093.   if (Protocol >= PROTOCOL_LANMAN1)
  2094.     {
  2095.       if(HAS_CACHED_ERROR(fnum))
  2096.     return (CACHED_ERROR(fnum));
  2097.     }
  2098.  
  2099.   count = IVAL(inbuf,smb_vwv1);
  2100.   offset = IVAL(inbuf,smb_vwv3);
  2101.  
  2102.   if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
  2103.     return (ERROR(eclass,ecode));
  2104.  
  2105.   DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
  2106.   
  2107.   return(outsize);
  2108. }
  2109.  
  2110.  
  2111. /****************************************************************************
  2112.   reply to a tdis
  2113. ****************************************************************************/
  2114. int reply_tdis(char *inbuf,char *outbuf)
  2115. {
  2116.   int cnum;
  2117.   int outsize = set_message(outbuf,0,0,True);
  2118.   
  2119.   cnum = SVAL(inbuf,smb_tid);
  2120.  
  2121.   close_cnum(cnum);
  2122.   
  2123.   DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
  2124.  
  2125.   return outsize;
  2126. }
  2127.  
  2128.  
  2129. /****************************************************************************
  2130.   reply to a echo
  2131. ****************************************************************************/
  2132. int reply_echo(char *inbuf,char *outbuf)
  2133. {
  2134.   int cnum;
  2135.   int smb_reverb = SVAL(inbuf,smb_vwv0);
  2136.   int seq_num;
  2137.   int data_len = smb_buflen(inbuf);
  2138.   int outsize = set_message(outbuf,1,data_len,True);
  2139.  
  2140.   cnum = SVAL(inbuf,smb_tid);
  2141.  
  2142.   if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
  2143.     {
  2144.       DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
  2145.       return(ERROR(ERRSRV,ERRinvnid));
  2146.     }
  2147.  
  2148.   /* copy any incoming data back out */
  2149.   if (data_len > 0)
  2150.     memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
  2151.  
  2152.   if (smb_reverb > 100)
  2153.     {
  2154.       DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
  2155.       smb_reverb = 100;
  2156.     }
  2157.  
  2158.   for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
  2159.     {
  2160.       SSVAL(outbuf,smb_vwv0,seq_num);
  2161.  
  2162.       smb_setlen(outbuf,outsize - 4);
  2163.  
  2164.       send_smb(outbuf);
  2165.     }
  2166.  
  2167.   DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
  2168.  
  2169.   return -1;
  2170. }
  2171.  
  2172.  
  2173. /****************************************************************************
  2174.   reply to a printopen
  2175. ****************************************************************************/
  2176. int reply_printopen(char *inbuf,char *outbuf)
  2177. {
  2178.   pstring fname="";
  2179.   pstring fname2="";
  2180.   int cnum;
  2181.   int fnum = -1;
  2182.   int outsize = 0;
  2183.   
  2184.   cnum = SVAL(inbuf,smb_tid);
  2185.  
  2186.   if (!CAN_PRINT(cnum))
  2187.     return(ERROR(ERRDOS,ERRnoaccess));
  2188.  
  2189.   {
  2190.     pstring s;
  2191.     char *p;
  2192.     StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
  2193.     p = s;
  2194.     while (*p)
  2195.       {
  2196.     if (!(isalnum(*p) || strchr("._-",*p)))
  2197.       *p = 'X';
  2198.     p++;
  2199.       }
  2200.  
  2201.     if (strlen(s) > 6) s[6] = 0;
  2202.  
  2203.     sprintf(fname,"%s.XXXXXX",s);  
  2204.   }
  2205.  
  2206.   fnum = find_free_file();
  2207.   if (fnum < 0)
  2208.     return(ERROR(ERRSRV,ERRnofids));
  2209.  
  2210.   strcpy(fname2,(char *)mktemp(fname));
  2211.  
  2212.   if (!check_name(fname2,cnum))
  2213.     return(ERROR(ERRDOS,ERRnoaccess));
  2214.  
  2215.   open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
  2216.         unix_mode(cnum,0));
  2217.  
  2218.   if (!Files[fnum].open)
  2219.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2220.  
  2221.   /* force it to be a print file */
  2222.   Files[fnum].print_file = True;
  2223.   
  2224.   outsize = set_message(outbuf,1,0,True);
  2225.   SSVAL(outbuf,smb_vwv0,fnum);
  2226.   
  2227.   DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum));
  2228.   
  2229.   return(outsize);
  2230. }
  2231.  
  2232.  
  2233. /****************************************************************************
  2234.   reply to a printclose
  2235. ****************************************************************************/
  2236. int reply_printclose(char *inbuf,char *outbuf)
  2237. {
  2238.   int fnum,cnum;
  2239.   int outsize = set_message(outbuf,0,0,True);
  2240.   
  2241.   cnum = SVAL(inbuf,smb_tid);
  2242.   fnum = GETFNUM(inbuf,smb_vwv0);
  2243.   if (!OPEN_FNUM(fnum))
  2244.     return(ERROR(ERRDOS,ERRbadfid));
  2245.   if (Protocol >= PROTOCOL_LANMAN1)
  2246.     {
  2247.       if(HAS_CACHED_ERROR(fnum))
  2248.     return (CACHED_ERROR(fnum));
  2249.     }
  2250.  
  2251.   if (!CAN_PRINT(cnum))
  2252.     return(ERROR(ERRDOS,ERRnoaccess));
  2253.   
  2254.   if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  2255.     close_file(fnum);
  2256.   
  2257.   DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum));
  2258.   
  2259.   return(outsize);
  2260. }
  2261.  
  2262.  
  2263. /****************************************************************************
  2264.   reply to a printqueue
  2265. ****************************************************************************/
  2266. int reply_printqueue(char *inbuf,char *outbuf)
  2267. {
  2268.   int cnum;
  2269.   int outsize = set_message(outbuf,2,3,True);
  2270.   int max_count = SVAL(inbuf,smb_vwv0);
  2271.   int start_index = SVAL(inbuf,smb_vwv1);
  2272.  
  2273.   cnum = SVAL(inbuf,smb_tid);
  2274.  
  2275. /* allow checking the queue for anyone */
  2276. #if 0
  2277.   if (!CAN_PRINT(cnum))
  2278.     return(ERROR(ERRDOS,ERRnoaccess));
  2279. #endif
  2280.  
  2281.   SSVAL(outbuf,smb_vwv0,0);
  2282.   SSVAL(outbuf,smb_vwv1,0);
  2283.   CVAL(smb_buf(outbuf),0) = 1;
  2284.   SSVAL(smb_buf(outbuf),1,0);
  2285.   
  2286.   DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
  2287.     timestring(),cnum,start_index,max_count));
  2288.  
  2289.   if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
  2290.     {
  2291.       int i;
  2292.       cnum = -1;
  2293.  
  2294.       for (i=0;i<MAX_CONNECTIONS;i++)
  2295.     if (CAN_PRINT(i) && Connections[i].printer)
  2296.       cnum = i;
  2297.  
  2298.       if (cnum == -1)
  2299.     for (i=0;i<MAX_CONNECTIONS;i++)
  2300.       if (OPEN_CNUM(i))
  2301.         cnum = i;
  2302.  
  2303.       if (!OPEN_CNUM(cnum))
  2304.     return(ERROR(ERRSRV,ERRinvnid));
  2305.  
  2306.       DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
  2307.     }
  2308.  
  2309.   if (!become_user(cnum))
  2310.     return(ERROR(ERRSRV,ERRinvnid));
  2311.  
  2312.   {
  2313.     print_queue_struct *queue = NULL;
  2314.     char *p = smb_buf(outbuf) + 3;
  2315.     int count = get_printqueue(SNUM(cnum),&queue);
  2316.     int num_to_get = ABS(max_count);
  2317.     int first = (max_count>0?start_index:start_index+max_count+1);
  2318.     int i;
  2319.  
  2320.     if (first >= count)
  2321.       num_to_get = 0;
  2322.     else
  2323.       num_to_get = MIN(num_to_get,count-first);
  2324.     
  2325.  
  2326.     for (i=first;i<first+num_to_get;i++)
  2327.       {
  2328.     put_dos_date2(p,0,queue[i].time);
  2329.     CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
  2330.     SSVAL(p,5,queue[i].job);
  2331.     SIVAL(p,7,queue[i].size);
  2332.     CVAL(p,11) = 0;
  2333.     StrnCpy(p+12,queue[i].user,16);
  2334.     p += 28;
  2335.       }
  2336.  
  2337.     if (count > 0)
  2338.       {
  2339.     outsize = set_message(outbuf,2,28*count+3,False);      
  2340.     SSVAL(outbuf,smb_vwv0,count);
  2341.     SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
  2342.     CVAL(smb_buf(outbuf),0) = 1;
  2343.     SSVAL(smb_buf(outbuf),1,28*count);
  2344.       }
  2345.  
  2346.     if (queue) free(queue);
  2347.       
  2348.     DEBUG(3,("%d entries returned in queue\n",count));
  2349.   }
  2350.   
  2351.   return(outsize);
  2352. }
  2353.  
  2354.  
  2355. /****************************************************************************
  2356.   reply to a printwrite
  2357. ****************************************************************************/
  2358. int reply_printwrite(char *inbuf,char *outbuf)
  2359. {
  2360.   int cnum,numtowrite,fnum;
  2361.   int outsize = set_message(outbuf,0,0,True);
  2362.   char *data;
  2363.   BOOL ok = False;
  2364.   
  2365.   cnum = SVAL(inbuf,smb_tid);
  2366.  
  2367.   if (!CAN_PRINT(cnum))
  2368.     return(ERROR(ERRDOS,ERRnoaccess));
  2369.  
  2370.   fnum = GETFNUM(inbuf,smb_vwv0);
  2371.  
  2372.   if (!OPEN_FNUM(fnum))
  2373.     return(ERROR(ERRDOS,ERRbadfid));
  2374.  
  2375.   if (Files[fnum].read_only)
  2376.     return(ERROR(ERRSRV,ERRaccess));
  2377.  
  2378.   if (Protocol >= PROTOCOL_LANMAN1)
  2379.     {
  2380.       if(HAS_CACHED_ERROR(fnum))
  2381.     return (CACHED_ERROR(fnum));
  2382.     }
  2383.  
  2384.   numtowrite = SVAL(smb_buf(inbuf),1);
  2385.   data = smb_buf(inbuf) + 3;
  2386.   
  2387.   if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  2388.     ok = (write(Files[fnum].fd,data,numtowrite) == numtowrite);
  2389.   
  2390.   if (!ok)
  2391.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2392.   
  2393.   DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
  2394.   
  2395.   return(outsize);
  2396. }
  2397.  
  2398.  
  2399. /****************************************************************************
  2400.   reply to a mkdir
  2401. ****************************************************************************/
  2402. int reply_mkdir(char *inbuf,char *outbuf)
  2403. {
  2404.   pstring directory="";
  2405.   int cnum;
  2406.   int outsize,ret=-1;
  2407.   
  2408.   strcpy(directory,smb_buf(inbuf) + 1);
  2409.   cnum = SVAL(inbuf,smb_tid);
  2410.   unix_convert(directory,cnum);
  2411.   
  2412.   if (check_name(directory,cnum))
  2413.     ret = mkdir(directory,unix_mode(cnum,aDIR));
  2414.   
  2415.   if (ret < 0)
  2416.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2417.   
  2418.   outsize = set_message(outbuf,0,0,True);
  2419.   
  2420.   DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
  2421.   
  2422.   return(outsize);
  2423. }
  2424.  
  2425.  
  2426. /****************************************************************************
  2427.   reply to a rmdir
  2428. ****************************************************************************/
  2429. int reply_rmdir(char *inbuf,char *outbuf)
  2430. {
  2431.   pstring directory="";
  2432.   int cnum;
  2433.   int outsize = 0;
  2434.   BOOL ok = False;
  2435.   
  2436.   cnum = SVAL(inbuf,smb_tid);
  2437.   strcpy(directory,smb_buf(inbuf) + 1);
  2438.   unix_convert(directory,cnum);
  2439.   
  2440.   if (check_name(directory,cnum))
  2441.     {
  2442.       dptr_closepath(directory,SVAL(inbuf,smb_pid));
  2443.       ok = (rmdir(directory) == 0);
  2444.       if (!ok)
  2445.     DEBUG(3,("couldn't remove directory %s : %s\n",
  2446.          directory,strerror(errno)));
  2447.     }
  2448.   
  2449.   if (!ok)
  2450.     return(UNIXERROR(ERRDOS,ERRbadpath));
  2451.   
  2452.   outsize = set_message(outbuf,0,0,True);
  2453.   
  2454.   DEBUG(3,("%s rmdir %s\n",timestring(),directory));
  2455.   
  2456.   return(outsize);
  2457. }
  2458.  
  2459.  
  2460. /****************************************************************************
  2461.   reply to a mv
  2462. ****************************************************************************/
  2463. int reply_mv(char *inbuf,char *outbuf)
  2464. {
  2465.   pstring oldname="";
  2466.   pstring newname="";
  2467.   int cnum;
  2468.   int outsize = 0;
  2469.   BOOL ok = False;
  2470.   
  2471.   strcpy(oldname,smb_buf(inbuf) + 1);
  2472.   strcpy(newname,smb_buf(inbuf) + 3 + strlen(oldname));
  2473.   
  2474.   cnum = SVAL(inbuf,smb_tid);
  2475.   unix_convert(oldname,cnum);
  2476.   unix_convert(newname,cnum);
  2477.   
  2478.   if (check_name(oldname,cnum) && check_name(newname,cnum))
  2479.     ok = (rename(oldname,newname) == 0);
  2480.   
  2481.   if (!ok)
  2482.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2483.   
  2484.   outsize = set_message(outbuf,0,0,True);
  2485.   
  2486.   DEBUG(3,("%s mv %s to %s cnum=%d\n",timestring(),oldname,newname,cnum));
  2487.   
  2488.   return(outsize);
  2489. }
  2490.  
  2491.  
  2492. /****************************************************************************
  2493.   reply to a setdir
  2494. ****************************************************************************/
  2495. int reply_setdir(char *inbuf,char *outbuf)
  2496. {
  2497.   int cnum,snum;
  2498.   int outsize = 0;
  2499.   BOOL ok = False;
  2500.   pstring newdir="";
  2501.   
  2502.   cnum = SVAL(inbuf,smb_tid);
  2503.   
  2504.   snum = Connections[cnum].service;
  2505.   if (!CAN_SETDIR(snum))
  2506.     return(ERROR(ERRDOS,ERRnoaccess));
  2507.   
  2508.   strcpy(newdir,smb_buf(inbuf) + 1);
  2509.   strlower(newdir);
  2510.   
  2511.   if (strlen(newdir) == 0)
  2512.     ok = True;
  2513.   else
  2514.     {
  2515.       ok = directory_exist(newdir);
  2516.       if (ok)
  2517.     strcpy(Connections[cnum].connectpath,newdir);
  2518.     }
  2519.   
  2520.   if (!ok)
  2521.     return(ERROR(ERRDOS,ERRbadpath));
  2522.   
  2523.   outsize = set_message(outbuf,0,0,True);
  2524.   CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
  2525.   
  2526.   DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
  2527.   
  2528.   return(outsize);
  2529. }
  2530.  
  2531.  
  2532. /****************************************************************************
  2533.   reply to a lockingX request
  2534. ****************************************************************************/
  2535. int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
  2536. {
  2537.   int smb_com2 = CVAL(inbuf,smb_vwv0);
  2538.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  2539.   int fnum = GETFNUM(inbuf,smb_vwv2);
  2540.   uint16 locktype = SVAL(inbuf,smb_vwv3);
  2541. #if 0
  2542.   uint32 timeout = IVAL(inbuf,smb_vwv4);
  2543. #endif
  2544.   uint16 num_locks = SVAL(inbuf,smb_vwv6);
  2545.   uint16 num_ulocks = SVAL(inbuf,smb_vwv7);
  2546.   uint32 count, offset;
  2547.  
  2548.   int cnum;
  2549.   int i;
  2550.   char *data;
  2551.   uint32 ecode, dummy2;
  2552.   int outsize, eclass, dummy1;
  2553.  
  2554.   cnum = SVAL(inbuf,smb_tid);
  2555.   if (!OPEN_FNUM(fnum))
  2556.     return(ERROR(ERRDOS,ERRbadfid));
  2557.  
  2558.   if (Protocol >= PROTOCOL_LANMAN1)
  2559.     {
  2560.       if(HAS_CACHED_ERROR(fnum))
  2561.     return (CACHED_ERROR(fnum));
  2562.     }
  2563.  
  2564.   data = smb_buf(inbuf);
  2565.   /* Data now points at the beginning of the list
  2566.      of smb_unlkrng structs */
  2567.   for(i = 0; i < (int)num_ulocks; i++) {
  2568.     count = IVAL(data,SMB_LKLEN_OFFSET(i));
  2569.     offset = IVAL(data,SMB_LKOFF_OFFSET(i));
  2570.     if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
  2571.       return ERROR(eclass,ecode);
  2572.   }
  2573.  
  2574.   /* Now do any requested locks */
  2575.   data += 10*num_ulocks;
  2576.   /* Data now points at the beginning of the list
  2577.      of smb_lkrng structs */
  2578.   for(i = 0; i < (int)num_locks; i++) {
  2579.     count = IVAL(data,SMB_LKLEN_OFFSET(i)); 
  2580.     offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
  2581.     if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
  2582.       break;
  2583.   }
  2584.  
  2585.   /* If any of the above locks failed, then we must unlock
  2586.      all of the previous locks (X/Open spec). */
  2587.   if(i != num_locks && num_locks != 0) {
  2588.     for(; i >= 0; i--) {
  2589.       count = IVAL(data,SMB_LKLEN_OFFSET(i));  
  2590.       offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
  2591.       do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
  2592.     }
  2593.     return ERROR(eclass,ecode);
  2594.   }
  2595.  
  2596.   outsize = set_message(outbuf,2,0,True);
  2597.   
  2598.   CVAL(outbuf,smb_vwv0) = smb_com2;
  2599.   SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
  2600.   
  2601.   DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
  2602.     timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
  2603.  
  2604.   chain_fnum = fnum;
  2605.  
  2606.   if (smb_com2 != 0xFF)
  2607.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  2608.                outbuf,outbuf+outsize,
  2609.                length,bufsize);
  2610.   
  2611.   chain_fnum = -1;
  2612.   
  2613.   return(outsize);
  2614. }
  2615.  
  2616.  
  2617. /****************************************************************************
  2618.   reply to a SMBreadbmpx (read block multiplex) request
  2619. ****************************************************************************/
  2620. int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
  2621. {
  2622.   int cnum,numtoread,fnum;
  2623.   int nread = -1;
  2624.   int total_read;
  2625.   char *data;
  2626.   int32 startpos;
  2627.   int32 timeout;
  2628.   int outsize, mincount, maxcount;
  2629.   BOOL ok = False, nonblocking = False;
  2630.   
  2631.   /* this function doesn't seem to work - disable by default */
  2632.   if (!lp_readbmpx())
  2633.     return(ERROR(ERRSRV,ERRuseSTD));
  2634.  
  2635.   outsize = set_message(outbuf,8,0,True);
  2636.  
  2637.   cnum = SVAL(inbuf,smb_tid);
  2638.   fnum = GETFNUM(inbuf,smb_vwv0);
  2639.   if (!OPEN_FNUM(fnum))
  2640.     return(ERROR(ERRDOS,ERRbadfid));
  2641.   if (Protocol >= PROTOCOL_LANMAN1)
  2642.     {
  2643.       if(HAS_CACHED_ERROR(fnum))
  2644.     return (CACHED_ERROR(fnum));
  2645.     }
  2646.  
  2647.   startpos = IVAL(inbuf,smb_vwv1);
  2648.   maxcount = SVAL(inbuf,smb_vwv3);
  2649.   mincount = SVAL(inbuf,smb_vwv4);
  2650.   timeout = IVALS(inbuf,smb_vwv5);
  2651.   if(timeout == 0)
  2652.     nonblocking = True;
  2653.  
  2654.   numtoread = MIN(bufsize-outsize,maxcount);
  2655.  
  2656.   if(numtoread < maxcount) 
  2657.     {
  2658.  
  2659.     /* We don't have enough space to read all the
  2660.        requested bytes into the buffer, so, while
  2661.        this is true we must send our own constructed
  2662.        SMB messages back, leaving one to be sent
  2663.        back as the return from this function.
  2664.        We *should* do this asynchronously so
  2665.        other SMB requests get a look in, but I
  2666.        want to finish LANMAN1.0 support before the end
  2667.        of the century, so..... */
  2668.  
  2669.     int new_bufsize = MIN(lp_maxxmit(),BUFFER_SIZE);
  2670.     char *new_outbuf = (char *)malloc(new_bufsize + SAFETY_MARGIN);
  2671.     int num_thisread=0;
  2672.     int new_maxcount = maxcount - numtoread; /* Max we should read
  2673.                         in these temp reads */
  2674.     int new_outsize, new_numtoread;
  2675.     int32 new_startpos = startpos;
  2676.  
  2677.     if(!new_outbuf) 
  2678.       {
  2679.     DEBUG(0,("Out of memory in reply_readmpx\n"));
  2680.     return(ERROR(ERRSRV,ERRnoresource));
  2681.       }
  2682.  
  2683.     /* Set up the smb header for this intermediate packet */
  2684.  
  2685.     memset(new_outbuf,0,smb_size);
  2686.     new_outsize = set_message(new_outbuf,8,0,True);
  2687.     CVAL(new_outbuf,smb_com) = CVAL(inbuf,smb_com);
  2688.     memcpy(new_outbuf+4,inbuf+4,4);
  2689.     CVAL(new_outbuf,smb_rcls) = SUCCESS;
  2690.     CVAL(new_outbuf,smb_reh) = 0;
  2691.     CVAL(new_outbuf,smb_flg) = 0x80; /* bit 7 set means a reply */
  2692.     SSVAL(new_outbuf,smb_err,SUCCESS);
  2693.     SSVAL(new_outbuf,smb_tid,SVAL(inbuf,smb_tid));
  2694.     SSVAL(new_outbuf,smb_pid,SVAL(inbuf,smb_pid));
  2695.     SSVAL(new_outbuf,smb_uid,SVAL(inbuf,smb_uid));
  2696.     SSVAL(new_outbuf,smb_mid,SVAL(inbuf,smb_mid));
  2697.  
  2698.     new_numtoread = MIN(new_bufsize-new_outsize,new_maxcount);
  2699.  
  2700.     /* Repeat until we have one read remaining */
  2701.     while( nread < new_maxcount)
  2702.       {
  2703.       ok = False;
  2704.       new_outsize = set_message(new_outbuf,8,0,True);
  2705.       data = smb_buf(new_outbuf);
  2706.   
  2707.     {
  2708.       if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  2709.         {
  2710.           if (is_locked(fnum,cnum,new_numtoread,new_startpos))
  2711.         {
  2712.           free(new_outbuf);
  2713.           return(ERROR(ERRDOS,ERRlock));
  2714.         }
  2715.  
  2716.  
  2717.           num_thisread = read_file(fnum,
  2718.                        data,
  2719.                        new_startpos,
  2720.                        mincount, new_numtoread,
  2721.                        timeout,
  2722.                        True);
  2723.           ok = True;
  2724.         }
  2725.     }
  2726.   
  2727.       if ((num_thisread < 0) || !ok) 
  2728.     {
  2729.       free(new_outbuf);
  2730.       return(UNIXERROR(ERRDOS,ERRnoaccess));
  2731.         }
  2732.  
  2733.       /* Update all the counts */
  2734.       nread += num_thisread;
  2735.       new_startpos += num_thisread;
  2736.  
  2737.       /* Now set up the buffer and send the message */
  2738.       new_outsize += num_thisread;
  2739.       SIVAL(new_outbuf,smb_vwv0, new_startpos - num_thisread);
  2740.       SSVAL(new_outbuf,smb_vwv2, maxcount);
  2741.       SSVAL(new_outbuf,smb_vwv3, -1); /* Don't support smb_remaining yet */
  2742.       SSVAL(new_outbuf,smb_vwv6, num_thisread);
  2743.       SSVAL(new_outbuf,smb_vwv7, smb_vwv9 - 4); /* Offset of data */
  2744.       SSVAL(new_outbuf,smb_vwv8, num_thisread); /* smb_bcc */
  2745.       smb_setlen(new_outbuf,new_outsize - 4);
  2746.       send_smb(new_outbuf);
  2747.  
  2748.       DEBUG(3,("%s intermediate readmpx fnum=%d cnum=%d num=%d start=%d nread=%d\n",
  2749.         timestring(),fnum,cnum,new_numtoread,new_startpos - num_thisread,
  2750.         num_thisread));
  2751.  
  2752.       }
  2753.  
  2754.     free(new_outbuf);
  2755.   }
  2756.  
  2757.   /* Here we know we have read nread bytes, so we have
  2758.      maxcount - nread bytes left to read. We know this
  2759.      will fit in outbuf because of the calculation we 
  2760.      did earlier.*/
  2761.  
  2762.   numtoread = maxcount - nread;
  2763.   startpos += nread;
  2764.   total_read = nread;
  2765.   nread = -1;
  2766.   ok = False;
  2767.  
  2768.   data = smb_buf(outbuf);
  2769.   
  2770.     {
  2771.       if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  2772.     {
  2773.       if (is_locked(fnum,cnum,numtoread,startpos))
  2774.         return(ERROR(ERRDOS,ERRlock));
  2775.  
  2776.       nread = read_file(fnum,
  2777.                 data,
  2778.                 startpos,
  2779.                 mincount, numtoread,
  2780.                 timeout,
  2781.                 True);
  2782.       ok = True;
  2783.     }
  2784.     }
  2785.   
  2786.   
  2787.   if ((nread < 0) || !ok)
  2788.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2789.  
  2790.   /* Update totals */
  2791.   outsize += nread;
  2792.   total_read += nread;
  2793.  
  2794.   /* Setup the final packet */
  2795.   SIVAL(outbuf,smb_vwv0, startpos);
  2796.   SSVAL(outbuf,smb_vwv2, total_read);
  2797.   SSVAL(outbuf,smb_vwv3, -1); /* Don't support smb_remaining yet */
  2798.   SSVAL(outbuf,smb_vwv6, nread);
  2799.   SSVAL(outbuf,smb_vwv7, smb_vwv9 - 4); /* Offset of data */
  2800.   SSVAL(outbuf,smb_vwv8, nread); /* smb_bcc */
  2801.   
  2802.   DEBUG(3,("%s readmpx fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
  2803.   
  2804.   return(outsize);
  2805. }
  2806.  
  2807.  
  2808. /****************************************************************************
  2809.   reply to a SMBwritebmpx (write block multiplex primary) request
  2810. ****************************************************************************/
  2811. int reply_writebmpx(char *inbuf,char *outbuf)
  2812. {
  2813.   int cnum,numtowrite,fnum;
  2814.   int nwritten = -1;
  2815.   int outsize = 0;
  2816.   int32 startpos, timeout;
  2817.   int tcount, write_through, smb_doff;
  2818.   int fd;
  2819.   char *data;
  2820.   BOOL ok = False;
  2821.   
  2822.   cnum = SVAL(inbuf,smb_tid);
  2823.   fnum = GETFNUM(inbuf,smb_vwv0);
  2824.  
  2825.   if (!OPEN_FNUM(fnum))
  2826.     return(ERROR(ERRDOS,ERRbadfid));
  2827.  
  2828.   if (Files[fnum].read_only)
  2829.     return(ERROR(ERRSRV,ERRaccess));
  2830.  
  2831.   if (Protocol >= PROTOCOL_LANMAN1)
  2832.     {
  2833.       if(HAS_CACHED_ERROR(fnum))
  2834.     return (CACHED_ERROR(fnum));
  2835.     }
  2836.  
  2837.   tcount = SVAL(inbuf,smb_vwv1);
  2838.   startpos = IVAL(inbuf,smb_vwv3);
  2839.   timeout = IVALS(inbuf,smb_vwv5);
  2840.   write_through = ((SVAL(inbuf,smb_vwv7) & 1) != 0);
  2841.   numtowrite = SVAL(inbuf,smb_vwv10);
  2842.   smb_doff = SVAL(inbuf,smb_vwv11);
  2843.  
  2844.   data = inbuf + 4 + smb_doff;
  2845.  
  2846.   /* If this fails we need to send an SMBwriteC response,
  2847.      not an SMBwritebmpx - set this up now so we don't forget */
  2848.   CVAL(outbuf,smb_com) = SMBwritec;
  2849.  
  2850.   fd = Files[fnum].fd;
  2851.  
  2852.   if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  2853.     {
  2854.       if (is_locked(fnum,cnum,numtowrite,startpos))
  2855.     return(ERROR(ERRDOS,ERRlock));
  2856.  
  2857.       seek_file(fnum,startpos);
  2858.       nwritten = write(fd,data,numtowrite);
  2859. #ifndef NO_FSYNC
  2860.       if(write_through)
  2861.     fsync(Files[fnum].fd);
  2862. #endif
  2863.  
  2864.       ok = True;
  2865.     }
  2866.   
  2867.   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0) || !ok)
  2868.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2869.  
  2870.   /* If the maximum to be written to this file
  2871.      is greater than what we just wrote then set
  2872.      up a secondary struct to be attached to this
  2873.      fd, we will use this to cache error messages etc. */
  2874.   if(tcount > nwritten) 
  2875.     {
  2876.     write_bmpx_struct *wbms;
  2877.     if(Files[fnum].wbmpx_ptr != NULL)
  2878.       wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
  2879.     else
  2880.       wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
  2881.     if(!wbms)
  2882.       {
  2883.     DEBUG(0,("Out of memory in reply_readmpx\n"));
  2884.     return(ERROR(ERRSRV,ERRnoresource));
  2885.       }
  2886.     wbms->wr_mode = write_through;
  2887.     wbms->wr_discard = False; /* No errors yet */
  2888.     wbms->wr_timeout = timeout;
  2889.     wbms->wr_total_written = nwritten;
  2890.     wbms->wr_errclass = 0;
  2891.     wbms->wr_error = 0;
  2892.     Files[fnum].wbmpx_ptr = wbms;
  2893.     }
  2894.  
  2895.   /* We are returning successfully, set the message type back to
  2896.      SMBwritebmpx */
  2897.   CVAL(outbuf,smb_com) = SMBwriteBmpx;
  2898.   
  2899.   outsize = set_message(outbuf,1,0,True);
  2900.   
  2901.   SSVAL(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
  2902.   
  2903.   DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
  2904.     timestring(),fnum,cnum,numtowrite,nwritten));
  2905.   
  2906.   return(outsize);
  2907. }
  2908.  
  2909.  
  2910. /****************************************************************************
  2911.   reply to a SMBsetattrE
  2912. ****************************************************************************/
  2913. int reply_setattrE(char *inbuf,char *outbuf)
  2914. {
  2915.   int cnum,fnum;
  2916.   struct utimbuf unix_times;
  2917.   int outsize = 0;
  2918.  
  2919.   outsize = set_message(outbuf,0,0,True);
  2920.  
  2921.   cnum = SVAL(inbuf,smb_tid);
  2922.   fnum = GETFNUM(inbuf,smb_vwv0);
  2923.   if (!OPEN_FNUM(fnum))
  2924.     return(ERROR(ERRDOS,ERRbadfid));
  2925.  
  2926.   if(HAS_CACHED_ERROR(fnum))
  2927.     return (CACHED_ERROR(fnum));
  2928.  
  2929.     {
  2930.       if(!(OPEN_FNUM(fnum)) || (Files[fnum].cnum != cnum))
  2931.     {
  2932.       return(ERROR(ERRDOS,ERRbadfid));
  2933.     }
  2934.  
  2935.       /* Convert the DOS times into dos times. Ignore create
  2936.      time as UNIX can't set this.
  2937.       */
  2938.  
  2939.       unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
  2940.       unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
  2941.       unix_times.actime += LOCAL_TO_GMT*TimeDiff();
  2942.       unix_times.modtime += LOCAL_TO_GMT*TimeDiff();
  2943.  
  2944.       /* Set the date on this file */
  2945.       if(utime(Files[fnum].name, &unix_times))
  2946.     return(ERROR(ERRDOS,ERRnoaccess));
  2947.  
  2948.     }
  2949.  
  2950.   DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
  2951.  
  2952.   return(outsize);
  2953. }
  2954.  
  2955.  
  2956. /****************************************************************************
  2957.   reply to a SMBgetattrE
  2958. ****************************************************************************/
  2959. int reply_getattrE(char *inbuf,char *outbuf)
  2960. {
  2961.   int cnum,fnum;
  2962.   struct stat sbuf;
  2963.   int outsize = 0;
  2964.  
  2965.   outsize = set_message(outbuf,11,0,True);
  2966.  
  2967.   cnum = SVAL(inbuf,smb_tid);
  2968.   fnum = GETFNUM(inbuf,smb_vwv0);
  2969.   if (!OPEN_FNUM(fnum))
  2970.     return(ERROR(ERRDOS,ERRbadfid));
  2971.  
  2972.   if(HAS_CACHED_ERROR(fnum))
  2973.     return (CACHED_ERROR(fnum));
  2974.  
  2975.     {
  2976.       int mode;
  2977.  
  2978.       if(!(OPEN_FNUM(fnum)) || (Files[fnum].cnum != cnum))
  2979.     return(ERROR(ERRDOS,ERRbadfid));
  2980.  
  2981.       /* Do an fstat on this file */
  2982.       if(fstat( Files[fnum].fd, &sbuf))
  2983.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2984.  
  2985.       mode = dos_mode(cnum,Files[fnum].name,&sbuf);
  2986.  
  2987.       /* Convert the times into dos times. Set create
  2988.      date to be last modify date as UNIX doesn't save
  2989.      this */
  2990.       put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
  2991.       put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
  2992.       put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
  2993.       if (mode & aDIR)
  2994.     {
  2995.       SIVAL(outbuf,smb_vwv6,0);
  2996.       SIVAL(outbuf,smb_vwv8,0);
  2997.     }
  2998.       else
  2999.     {
  3000.       SIVAL(outbuf,smb_vwv6,sbuf.st_size);
  3001.       SIVAL(outbuf,smb_vwv8,sbuf.st_size);
  3002.     }
  3003.       SSVAL(outbuf,smb_vwv10, mode);
  3004.  
  3005.     }
  3006.  
  3007.   DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
  3008.  
  3009.   return(outsize);
  3010. }
  3011.  
  3012.  
  3013. /****************************************************************************
  3014.   reply to a SMBwritebs (write block multiplex secondary) request
  3015. ****************************************************************************/
  3016. int reply_writebs(char *inbuf,char *outbuf)
  3017. {
  3018.   int cnum,numtowrite,fnum;
  3019.   int nwritten = -1;
  3020.   int outsize = 0;
  3021.   int32 startpos;
  3022.   int tcount, write_through, smb_doff;
  3023.   int fd;
  3024.   char *data;
  3025.   write_bmpx_struct *wbms;
  3026.   BOOL ok = False;
  3027.   
  3028.   cnum = SVAL(inbuf,smb_tid);
  3029.   fnum = GETFNUM(inbuf,smb_vwv0);
  3030.   if (!OPEN_FNUM(fnum))
  3031.     return(ERROR(ERRDOS,ERRbadfid));
  3032.  
  3033.   if (Files[fnum].read_only)
  3034.     return(ERROR(ERRSRV,ERRaccess));    
  3035.  
  3036.   tcount = SVAL(inbuf,smb_vwv1);
  3037.   startpos = IVAL(inbuf,smb_vwv2);
  3038.   numtowrite = SVAL(inbuf,smb_vwv6);
  3039.   smb_doff = SVAL(inbuf,smb_vwv7);
  3040.  
  3041.   data = inbuf + 4 + smb_doff;
  3042.  
  3043.   /* We need to send an SMBwriteC response, not an SMBwritebs */
  3044.   CVAL(outbuf,smb_com) = SMBwritec;
  3045.  
  3046.   /* This fd should have an auxiliary struct attached,
  3047.      check that it does */
  3048.   wbms = Files[fnum].wbmpx_ptr;
  3049.   if(!wbms) /* smbd is confused - it can't do this ! */
  3050.     return(ERROR(ERRDOS,ERRnoaccess));
  3051.  
  3052.   /* If write through is set we can return errors, else we must
  3053.      cache them */
  3054.   write_through = wbms->wr_mode;
  3055.  
  3056.   /* Check for an earlier error */
  3057.   if(wbms->wr_discard)
  3058.     return -1; /* Just discard the packet */
  3059.  
  3060.   if (Files[fnum].read_only)
  3061.     {
  3062.       if(write_through)
  3063.     return(ERROR(ERRSRV,ERRaccess));
  3064.       /* Cache the error - it must be returned by another
  3065.      file request */
  3066.       return(CACHE_ERROR(wbms,ERRSRV,ERRaccess));
  3067.     }
  3068.     
  3069.   fd = Files[fnum].fd;
  3070.  
  3071.   if (OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  3072.     {
  3073.       if (is_locked(fnum,cnum,numtowrite,startpos))
  3074.     {
  3075.       if(write_through)
  3076.         {
  3077.           /* We are returning an error - delete the aux struct */
  3078.           if (wbms) free((char *)wbms);
  3079.           Files[fnum].wbmpx_ptr = NULL;
  3080.           return(ERROR(ERRDOS,ERRlock));
  3081.         }
  3082.       return CACHE_ERROR(wbms,ERRDOS,ERRlock);
  3083.     }
  3084.  
  3085.       seek_file(fnum,startpos);
  3086.       nwritten = write(fd,data,numtowrite);
  3087. #ifndef NO_FSYNC
  3088.       if(write_through)
  3089.     fsync(Files[fnum].fd);
  3090. #endif
  3091.       ok = True;
  3092.     }
  3093.   
  3094.   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0) || !ok)
  3095.     {
  3096.       if(write_through)
  3097.     {
  3098.       /* We are returning an error - we can delete the aux struct */
  3099.       if (wbms) free((char *)wbms);
  3100.       Files[fnum].wbmpx_ptr = NULL;
  3101.       return(ERROR(ERRDOS,ERRnoaccess));
  3102.     }
  3103.       return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
  3104.     }
  3105.  
  3106.   /* Increment the total written, if this matches tcount
  3107.      we can discard the auxiliary struct (hurrah !) */
  3108.   wbms->wr_total_written += nwritten;
  3109.   if(wbms->wr_total_written >= tcount)
  3110.     {
  3111.     free((char *)wbms);
  3112.     Files[fnum].wbmpx_ptr = NULL;
  3113.     }
  3114.      
  3115.   outsize = set_message(outbuf,1,0,True);
  3116.   
  3117.   SSVAL(outbuf,smb_vwv0,nwritten);
  3118.   
  3119.   DEBUG(3,("%s writebmpx secondary fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
  3120.  
  3121.   if(!write_through)
  3122.     return -1; /* Don't bother with a response */
  3123.  
  3124.   return(outsize);
  3125. }
  3126.