Fixed up incorrect calls to read_file().
[samba.git] / source3 / smbd / reply.c
index db494d07dbd6869329c9cd6702368c79ec14e9ab..51d737a784cd061a120cb5ad5c75e78a7282a3b2 100644 (file)
@@ -33,21 +33,15 @@ extern int Protocol;
 extern int DEBUGLEVEL;
 extern int max_send;
 extern int max_recv;
-extern int chain_fnum;
 extern char magic_char;
-extern connection_struct Connections[];
-extern files_struct Files[];
 extern BOOL case_sensitive;
 extern BOOL case_preserve;
 extern BOOL short_case_preserve;
 extern pstring sesssetup_user;
-extern fstring myworkgroup;
+extern fstring global_myworkgroup;
 extern int Client;
 extern int global_oplock_break;
-
-/* this macro should always be used to extract an fnum (smb_fid) from
-a packet to ensure chaining works correctly */
-#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
+uint32 global_client_caps = 0;
 
 
 /****************************************************************************
@@ -55,13 +49,62 @@ report a possible attack via the password buffer overflow bug
 ****************************************************************************/
 static void overflow_attack(int len)
 {
-       DEBUG(0,("%s: ERROR: Invalid password length %d\n", timestring(), len));
-       DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n"));
-       DEBUG(0,("Attack was from IP=%s\n", client_addr()));
+        if( DEBUGLVL( 0 ) )
+          {
+         dbgtext( "ERROR: Invalid password length %d.\n", len );
+         dbgtext( "Your machine may be under attack by someone " );
+          dbgtext( "attempting to exploit an old bug.\n" );
+         dbgtext( "Attack was from IP = %s.\n", client_addr(Client) );
+          }
        exit_server("possible attack");
 }
 
 
+/****************************************************************************
+  does _both_ nt->unix and unix->unix username remappings.
+****************************************************************************/
+static void map_nt_and_unix_username(const char *domain, char *user)
+{
+       DOM_NAME_MAP gmep;
+       fstring nt_username;
+
+       /*
+        * Pass the user through the NT -> unix user mapping
+        * function.
+        */
+   
+       if (lp_server_role() != ROLE_DOMAIN_NONE)
+       {
+               memset(nt_username, 0, sizeof(nt_username));
+               if (domain != NULL)
+               {
+                       slprintf(nt_username, sizeof(nt_username)-1, "%s\\%s",
+                                domain, user);
+               }
+               else
+               {
+                       fstrcpy(nt_username, user);
+               }
+
+               if (lookupsmbpwntnam(nt_username, &gmep))
+               {
+                       fstrcpy(user, gmep.unix_name);
+               }
+       }
+
+       /*
+        * Pass the user through the unix -> unix user mapping
+        * function.
+        */
+
+       (void)map_username(user);
+
+       /*
+        * Do any UNIX username case mangling.
+        */
+       (void)Get_Pwnam( user, True);
+}
+
 /****************************************************************************
   reply to an special message 
 ****************************************************************************/
@@ -78,6 +121,8 @@ int reply_special(char *inbuf,char *outbuf)
        
        *name1 = *name2 = 0;
        
+       bzero(outbuf,smb_size);
+
        smb_setlen(outbuf,0);
        
        switch (msg_type) {
@@ -120,6 +165,10 @@ int reply_special(char *inbuf,char *outbuf)
                reload_services(True);
                reopen_logs();
 
+               if (lp_status(-1)) {
+                       claim_connection(NULL,"STATUS.",MAXSTATUS,True);
+               }
+
                break;
                
        case 0x89: /* session keepalive request 
@@ -139,8 +188,8 @@ int reply_special(char *inbuf,char *outbuf)
                return(0);
        }
        
-       DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
-                timestring(),msg_type,msg_flags));
+       DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
+                   msg_type, msg_flags));
        
        return(outsize);
 }
@@ -149,26 +198,13 @@ int reply_special(char *inbuf,char *outbuf)
 /*******************************************************************
 work out what error to give to a failed connection
 ********************************************************************/
-static int connection_error(char *inbuf,char *outbuf,int connection_num)
+static int connection_error(char *inbuf,char *outbuf,int ecode)
 {
-  switch (connection_num)
-    {
-    case -8:
-      return(ERROR(ERRSRV,ERRnoresource));
-    case -7:
-      return(ERROR(ERRSRV,ERRbaduid));
-    case -6:
-      return(ERROR(ERRSRV,ERRinvdevice));
-    case -5:
-      return(ERROR(ERRSRV,ERRinvnetname));
-    case -4:
-      return(ERROR(ERRSRV,ERRaccess));
-    case -3:
-      return(ERROR(ERRDOS,ERRnoipc));
-    case -2:
-      return(ERROR(ERRSRV,ERRinvnetname));
-    }
-  return(ERROR(ERRSRV,ERRbadpw));
+       if (ecode == ERRnoipc) {
+               return(ERROR(ERRDOS,ERRnoipc));
+       }
+
+       return(ERROR(ERRSRV,ecode));
 }
 
 
@@ -213,122 +249,126 @@ static void parse_connect(char *p,char *service,char *user,
 /****************************************************************************
   reply to a tcon
 ****************************************************************************/
-int reply_tcon(char *inbuf,char *outbuf)
+int reply_tcon(connection_struct *conn,
+              char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  pstring service;
-  pstring user;
-  pstring password;
-  pstring dev;
-  int connection_num;
-  int outsize = 0;
-  uint16 vuid = SVAL(inbuf,smb_uid);
-  int pwlen=0;
+       pstring service;
+       pstring user;
+       pstring password;
+       pstring dev;
+       int outsize = 0;
+       uint16 vuid = SVAL(inbuf,smb_uid);
+       int pwlen=0;
+       int ecode = -1;
 
-  *service = *user = *password = *dev = 0;
+       *service = *user = *password = *dev = 0;
 
-  parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
+       parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
 
-  connection_num = make_connection(service,user,password,pwlen,dev,vuid);
+       map_nt_and_unix_username(global_myworkgroup, user);
+
+       conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
   
-  if (connection_num < 0)
-    return(connection_error(inbuf,outbuf,connection_num));
+       if (!conn) {
+               return(connection_error(inbuf,outbuf,ecode));
+       }
   
-  outsize = set_message(outbuf,2,0,True);
-  SSVAL(outbuf,smb_vwv0,max_recv);
-  SSVAL(outbuf,smb_vwv1,connection_num);
-  SSVAL(outbuf,smb_tid,connection_num);
+       outsize = set_message(outbuf,2,0,True);
+       SSVAL(outbuf,smb_vwv0,max_recv);
+       SSVAL(outbuf,smb_vwv1,conn->cnum);
+       SSVAL(outbuf,smb_tid,conn->cnum);
   
-  DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
+       DEBUG(3,("tcon service=%s user=%s cnum=%d\n", 
+                service, user, conn->cnum));
   
-  return(outsize);
+       return(outsize);
 }
 
 
 /****************************************************************************
   reply to a tcon and X
 ****************************************************************************/
-int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
+int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
-  pstring service;
-  pstring user;
-  pstring password;
-  pstring devicename;
-  int connection_num;
-  uint16 vuid = SVAL(inbuf,smb_uid);
-  int passlen = SVAL(inbuf,smb_vwv3);
-
-  *service = *user = *password = *devicename = 0;
+       pstring service;
+       pstring user;
+       pstring password;
+       pstring devicename;
+       int ecode = -1;
+       uint16 vuid = SVAL(inbuf,smb_uid);
+       int passlen = SVAL(inbuf,smb_vwv3);
+       char *path;
+       char *p;
+       
+       *service = *user = *password = *devicename = 0;
 
-  /* we might have to close an old one */
-  if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
-    close_cnum(SVAL(inbuf,smb_tid),vuid);
+       /* we might have to close an old one */
+       if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
+               close_cnum(conn,vuid);
+       }
 
-  if (passlen > MAX_PASS_LEN) {
-         overflow_attack(passlen);
-  }
+       if (passlen > MAX_PASS_LEN) {
+               overflow_attack(passlen);
+       }
   
-  {
-    char *path;
-    char *p;
-    memcpy(password,smb_buf(inbuf),passlen);
-    password[passlen]=0;    
-    path = smb_buf(inbuf) + passlen;
-
-    if (passlen != 24) {
-      if (strequal(password," "))
-       *password = 0;
-      passlen = strlen(password);
-    }
-    
-    fstrcpy(service,path+2);
-    p = strchr(service,'\\');
-    if (!p)
-      return(ERROR(ERRSRV,ERRinvnetname));
-    *p = 0;
-    fstrcpy(service,p+1);
-    p = strchr(service,'%');
-    if (p)
-      {
-       *p++ = 0;
-       fstrcpy(user,p);
-      }
-    StrnCpy(devicename,path + strlen(path) + 1,6);
-    DEBUG(4,("Got device type %s\n",devicename));
-  }
+       memcpy(password,smb_buf(inbuf),passlen);
+       password[passlen]=0;    
+       path = smb_buf(inbuf) + passlen;
 
-  connection_num = make_connection(service,user,password,passlen,devicename,vuid);
-  
-  if (connection_num < 0)
-    return(connection_error(inbuf,outbuf,connection_num));
+       if (passlen != 24) {
+               if (strequal(password," "))
+                       *password = 0;
+               passlen = strlen(password);
+       }
+       
+       fstrcpy(service,path+2);
+       p = strchr(service,'\\');
+       if (!p)
+               return(ERROR(ERRSRV,ERRinvnetname));
+       *p = 0;
+       fstrcpy(service,p+1);
+       p = strchr(service,'%');
+       if (p) {
+               *p++ = 0;
+               fstrcpy(user,p);
+       }
+       StrnCpy(devicename,path + strlen(path) + 1,6);
+       DEBUG(4,("Got device type %s\n",devicename));
 
-  if (Protocol < PROTOCOL_NT1)
-  {
-    set_message(outbuf,2,strlen(devicename)+1,True);
-    strcpy(smb_buf(outbuf),devicename);
-  }
-  else
-  {
-    char *fsname = "SAMBA";
-    char *p;
+       map_nt_and_unix_username(global_myworkgroup, user);
 
-    set_message(outbuf,3,3,True);
+       conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
+       
+       if (!conn)
+               return(connection_error(inbuf,outbuf,ecode));
 
-    p = smb_buf(outbuf);
-    strcpy(p,devicename); p = skip_string(p,1); /* device name */
-    strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
+       if (Protocol < PROTOCOL_NT1) {
+               set_message(outbuf,2,strlen(devicename)+1,True);
+               pstrcpy(smb_buf(outbuf),devicename);
+       } else {
+               char *fsname = lp_fstype(SNUM(conn));
 
-    set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
+               set_message(outbuf,3,3,True);
 
-    SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
-  }
+               p = smb_buf(outbuf);
+               pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
+               pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
+               
+               set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
+               
+               /* what does setting this bit do? It is set by NT4 and
+                  may affect the ability to autorun mounted cdroms */
+               SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS); 
+       }
   
-  DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
+       DEBUG(3,("tconX service=%s user=%s\n",
+                service, user));
   
-  /* set the incoming and outgoing tid to the just created one */
-  SSVAL(inbuf,smb_tid,connection_num);
-  SSVAL(outbuf,smb_tid,connection_num);
+       /* set the incoming and outgoing tid to the just created one */
+       SSVAL(inbuf,smb_tid,conn->cnum);
+       SSVAL(outbuf,smb_tid,conn->cnum);
 
-  return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
 
@@ -337,56 +377,152 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 ****************************************************************************/
 int reply_unknown(char *inbuf,char *outbuf)
 {
-  int cnum;
-  int type;
-  cnum = SVAL(inbuf,smb_tid);
-  type = CVAL(inbuf,smb_com);
+       int type;
+       type = CVAL(inbuf,smb_com);
   
-  DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
-       timestring(),
-       smb_fn_name(type),
-       cnum,type,type));
+       DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
+                smb_fn_name(type), type, type));
   
-  return(ERROR(ERRSRV,ERRunknownsmb));
+       return(ERROR(ERRSRV,ERRunknownsmb));
 }
 
 
 /****************************************************************************
   reply to an ioctl
 ****************************************************************************/
-int reply_ioctl(char *inbuf,char *outbuf)
+int reply_ioctl(connection_struct *conn,
+               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  DEBUG(3,("ignoring ioctl\n"));
+       DEBUG(3,("ignoring ioctl\n"));
 #if 0
-  /* we just say it succeeds and hope its all OK. 
-     some day it would be nice to interpret them individually */
-  return set_message(outbuf,1,0,True); 
+       /* we just say it succeeds and hope its all OK. 
+          some day it would be nice to interpret them individually */
+       return set_message(outbuf,1,0,True); 
 #else
-  return(ERROR(ERRSRV,ERRnosupport));
+       return(ERROR(ERRSRV,ERRnosupport));
 #endif
 }
 
+/****************************************************************************
+ always return an error: it's just a matter of which one...
+ ****************************************************************************/
+static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
+                                char *smb_passwd, int smb_passlen,
+                                char *smb_nt_passwd, int smb_nt_passlen)
+{
+  struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
+  if (lp_security() == SEC_USER)
+  {
+    smb_trust_acct = getsmbpwnam(user);
+  }
+  else
+  {
+    DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
+    SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+    return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
+  }
+
+  if (smb_trust_acct == NULL)
+  {
+    /* lkclXXXX: workstation entry doesn't exist */
+    DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
+    SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+    return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
+  }
+  else
+  {
+    if ((smb_passlen != 24) || (smb_nt_passlen != 24))
+    {
+      DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
+      SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+      return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
+    }
+
+    if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
+    {
+      DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
+      SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+      return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
+    }
+
+    if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
+    {
+      DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
+      SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+      return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
+    }
+
+    if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
+    {
+      DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
+      SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+      return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
+    }
+
+    if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
+    {
+      DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
+      SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+      return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
+    }
+  }
+
+  /* don't know what to do: indicate logon failure */
+  SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+  return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
+}
+
+/****************************************************************************
+ Check for a valid username and password in security=server mode.
+****************************************************************************/
+
+static BOOL check_server_security(char *orig_user, char *domain, 
+                                  char *smb_apasswd, int smb_apasslen,
+                                  char *smb_ntpasswd, int smb_ntpasslen)
+{
+  if(lp_security() != SEC_SERVER)
+    return False;
+
+  return server_validate(orig_user, domain, 
+                            smb_apasswd, smb_apasslen, 
+                            smb_ntpasswd, smb_ntpasslen);
+}
+
+/****************************************************************************
+ Check for a valid username and password in security=domain mode.
+****************************************************************************/
+
+static BOOL check_domain_security(char *orig_user, char *domain, 
+                                  char *smb_apasswd, int smb_apasslen,
+                                  char *smb_ntpasswd, int smb_ntpasslen)
+{
+  if(lp_security() != SEC_DOMAIN)
+    return False;
+
+  return domain_client_validate(orig_user, domain,
+                                smb_apasswd, smb_apasslen,
+                                smb_ntpasswd, smb_ntpasslen);
+}
 
 /****************************************************************************
 reply to a session setup command
 ****************************************************************************/
-int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
+
+int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
   uint16 sess_vuid;
+  uchar user_sess_key[16];
   int gid;
   int uid;
   int   smb_bufsize;    
-  int   smb_mpxmax;     
-  int   smb_vc_num;     
-  uint32   smb_sesskey;    
   int   smb_apasslen = 0;   
   pstring smb_apasswd;
   int   smb_ntpasslen = 0;   
   pstring smb_ntpasswd;
   BOOL valid_nt_password = False;
   pstring user;
+  pstring orig_user;
   BOOL guest=False;
-  BOOL computer_id=False;
   static BOOL done_sesssetup = False;
   BOOL doencrypt = SMBENCRYPT();
   char *domain = "";
@@ -395,9 +531,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   *smb_ntpasswd = 0;
   
   smb_bufsize = SVAL(inbuf,smb_vwv2);
-  smb_mpxmax = SVAL(inbuf,smb_vwv3);
-  smb_vc_num = SVAL(inbuf,smb_vwv4);
-  smb_sesskey = IVAL(inbuf,smb_vwv5);
 
   if (Protocol < PROTOCOL_NT1) {
     smb_apasslen = SVAL(inbuf,smb_vwv7);
@@ -416,11 +549,11 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   } else {
     uint16 passlen1 = SVAL(inbuf,smb_vwv7);
     uint16 passlen2 = SVAL(inbuf,smb_vwv8);
-    uint32 client_caps = IVAL(inbuf,smb_vwv11);
     enum remote_arch_types ra_type = get_remote_arch();
-
     char *p = smb_buf(inbuf);    
 
+    global_client_caps = IVAL(inbuf,smb_vwv11);
+
     /* client_caps is used as final determination if client is NT or Win95. 
        This is needed to return the correct error codes in some
        circumstances.
@@ -428,7 +561,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     
     if(ra_type == RA_WINNT || ra_type == RA_WIN95)
     {
-      if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
+      if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
         set_remote_arch( RA_WINNT);
       else
         set_remote_arch( RA_WIN95);
@@ -444,7 +577,24 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     passlen1 = MIN(passlen1, MAX_PASS_LEN);
     passlen2 = MIN(passlen2, MAX_PASS_LEN);
 
-    if(doencrypt || (lp_security() == SEC_SERVER)) {
+    if(!doencrypt) {
+       /* both Win95 and WinNT stuff up the password lengths for
+          non-encrypting systems. Uggh. 
+      
+          if passlen1==24 its a win95 system, and its setting the
+          password length incorrectly. Luckily it still works with the
+          default code because Win95 will null terminate the password
+          anyway 
+
+          if passlen1>0 and passlen2>0 then maybe its a NT box and its
+          setting passlen2 to some random value which really stuffs
+          things up. we need to fix that one.  */
+
+      if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
+        passlen2 = 0;
+    }
+
+    if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
       /* Save the lanman2 password and the NT md4 password. */
       smb_apasslen = passlen1;
       memcpy(smb_apasswd,p,smb_apasslen);
@@ -453,21 +603,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
       memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
       smb_ntpasswd[smb_ntpasslen] = 0;
     } else {
-      /* both Win95 and WinNT stuff up the password lengths for
-        non-encrypting systems. Uggh. 
-      
-        if passlen1==24 its a win95 system, and its setting the
-        password length incorrectly. Luckily it still works with the
-        default code because Win95 will null terminate the password
-        anyway 
-
-        if passlen1>0 and passlen2>0 then maybe its a NT box and its
-        setting passlen2 to some random value which really stuffs
-        things up. we need to fix that one.  */
-      if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
-         passlen2 != 1) {
-       passlen2 = 0;
-      }
       /* we use the first password that they gave */
       smb_apasslen = passlen1;
       StrnCpy(smb_apasswd,p,smb_apasslen);      
@@ -490,130 +625,135 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
             domain,skip_string(p,1),skip_string(p,2)));
   }
 
-
   DEBUG(3,("sesssetupX:name=[%s]\n",user));
 
   /* If name ends in $ then I think it's asking about whether a */
   /* computer with that name (minus the $) has access. For now */
   /* say yes to everything ending in $. */
-  if (user[strlen(user) - 1] == '$')
+  if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
   {
-#ifdef NTDOMAIN
-    struct smb_passwd *smb_pass; /* To check if machine account exists */
-/* 
-   PAXX: Ack. We don't want to do this. The workstation trust account
-   with a $ on the end should exist in the local password database
-   or be mapped to something generic, but not modified. For NT
-   domain support we must reject this used in certain circumstances
-   with a code to indicate to the client that it is an invalid use
-   of a workstation trust account. NTWKS needs this error to join
-   a domain. This may be the source of future bugs if we cannot
-   be sure whether to reject this or not.
-*/
-   /* non-null user name indicates search by username not by smb userid */
-   smb_pass = get_smbpwd_entry(user, 0);
-
-   if (!smb_pass)
-   {
-     /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */
-     DEBUG(4,("Workstation trust account %s doesn't exist.",user));
-     SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
-     CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
-     return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */
-   }
-   else
-   {
-     /* PAXX: This is the NO LOGON workstation trust account stuff */
-     /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */
-     DEBUG(4,("No Workstation trust account %s",user));
-     SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
-     CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
-     return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */
-   }
-
-   computer_id = True;
-#else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */
-    user[strlen(user) - 1] = '\0';
-#endif
+    return session_trust_account(conn, inbuf, outbuf, user, 
+                                 smb_apasswd, smb_apasslen,
+                                 smb_ntpasswd, smb_ntpasslen);
   }
 
-
   /* If no username is sent use the guest account */
   if (!*user)
-    {
-      strcpy(user,lp_guestaccount(-1));
-      /* If no user and no password then set guest flag. */
-      if( *smb_apasswd == 0)
-        guest = True;
-    }
+  {
+    pstrcpy(user,lp_guestaccount(-1));
+    /* If no user and no password then set guest flag. */
+    if( *smb_apasswd == 0)
+      guest = True;
+  }
 
   strlower(user);
+  /*
+   * In share level security, only overwrite sesssetup_use if
+   * it's a non null-session share. Helps keep %U and %G
+   * working.
+   */
 
-  strcpy(sesssetup_user,user);
-
+  if((lp_security() != SEC_SHARE) || (*user && !guest))
+    pstrcpy(sesssetup_user,user);
   reload_services(True);
 
+  /*
+   * Save the username before mapping. We will use
+   * the original username sent to us for security=server
+   * and security=domain checking.
+   */
+
+  pstrcpy( orig_user, user);
+
+  map_nt_and_unix_username(domain, user);
+
   add_session_user(user);
 
-  /* Check if the given username was the guest user with no password.
-     We need to do this check after add_session_user() as that
-     call can potentially change the username (via map_user).
+  /*
+   * Check if the given username was the guest user with no password.
    */
 
   if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
     guest = True;
 
-  if (!guest && !(lp_security() == SEC_SERVER && 
-                 server_validate(user, domain, 
-                                 smb_apasswd, smb_apasslen, 
-                                 smb_ntpasswd, smb_ntpasslen)) &&
-      !check_hosts_equiv(user))
+  /* 
+   * Check with orig_user for security=server and
+   * security=domain.
+   */
+
+  if (!guest && 
+      !check_server_security(orig_user, domain,
+                             smb_apasswd, smb_apasslen,
+                             smb_ntpasswd, smb_ntpasslen) &&
+      !check_domain_security(orig_user, domain,
+                             smb_apasswd, smb_apasslen,
+                             smb_ntpasswd, smb_ntpasslen) &&
+      !check_hosts_equiv(user)
+     )
+  {
+
+    /* 
+     * If we get here then the user wasn't guest and the remote
+     * authentication methods failed. Check the authentication
+     * methods on this local server.
+     *
+     * If an NT password was supplied try and validate with that
+     * first. This is superior as the passwords are mixed case 
+     * 128 length unicode.
+      */
+
+    if(smb_ntpasslen)
     {
+      if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key))
+        DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
+      else
+        valid_nt_password = True;
+    } 
 
-      /* now check if it's a valid username/password */
-      /* If an NT password was supplied try and validate with that
-        first. This is superior as the passwords are mixed case 
-         128 length unicode */
-      if(smb_ntpasslen)
-       {
-         if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
-           DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
-         else
-           valid_nt_password = True;
-       } 
-      if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
-       {
-         if (!computer_id && lp_security() >= SEC_USER) {
-#if (GUEST_SESSSETUP == 0)
-           return(ERROR(ERRSRV,ERRbadpw));
-#endif
-#if (GUEST_SESSSETUP == 1)
-           if (Get_Pwnam(user,True))
-             return(ERROR(ERRSRV,ERRbadpw));
-#endif
-         }
-         if (*smb_apasswd || !Get_Pwnam(user,True))
-           strcpy(user,lp_guestaccount(-1));
-         DEBUG(3,("Registered username %s for guest access\n",user));
-         guest = True;
-       }
+    if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key))
+    {
+      if (lp_security() >= SEC_USER) 
+      {
+        if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
+          return(ERROR(ERRSRV,ERRbadpw));
+
+        if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
+        {
+         if (Get_Pwnam(user,True))
+            return(ERROR(ERRSRV,ERRbadpw));
+        }
+
+        /*
+         * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
+         * Then always map to guest account - as done below.
+         */
+      }
+
+      if (*smb_apasswd || !Get_Pwnam(user,True))
+         pstrcpy(user,lp_guestaccount(-1));
+      DEBUG(3,("Registered username %s for guest access\n",user));
+      guest = True;
     }
+  }
 
   if (!Get_Pwnam(user,True)) {
     DEBUG(3,("No such user %s - using guest account\n",user));
-    strcpy(user,lp_guestaccount(-1));
+    pstrcpy(user,lp_guestaccount(-1));
     guest = True;
   }
 
   if (!strequal(user,lp_guestaccount(-1)) &&
       lp_servicenumber(user) < 0)      
-    {
-      int homes = lp_servicenumber(HOMES_NAME);
-      char *home = get_home_dir(user);
-      if (homes >= 0 && home)
-       lp_add_home(user,homes,home);
-    }
-
+  {
+    int homes = lp_servicenumber(HOMES_NAME);
+    char *home = get_home_dir(user);
+    if (homes >= 0 && home)
+       {
+               pstring home_dir;
+               fstrcpy(home_dir, home);
+               lp_add_home(user,homes,home_dir);
+       }
+  }
 
   /* it's ok - setup a reply */
   if (Protocol < PROTOCOL_NT1) {
@@ -622,9 +762,9 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     char *p;
     set_message(outbuf,3,3,True);
     p = smb_buf(outbuf);
-    strcpy(p,"Unix"); p = skip_string(p,1);
-    strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
-    strcpy(p,myworkgroup); p = skip_string(p,1);
+    pstrcpy(p,"Unix"); p = skip_string(p,1);
+    pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
+    pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
     set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
     /* perhaps grab OS version here?? */
   }
@@ -643,12 +783,12 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     uid = pw->pw_uid;
   }
 
-  if (guest && !computer_id)
+  if (guest)
     SSVAL(outbuf,smb_vwv2,1);
 
   /* register the name and uid as being validated, so further connections
      to a uid can get through without a password, on the same VC */
-  sess_vuid = register_vuid(uid,gid,user,guest);
+  sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key);
  
   SSVAL(outbuf,smb_uid,sess_vuid);
   SSVAL(inbuf,smb_uid,sess_vuid);
@@ -667,23 +807,26 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 /****************************************************************************
   reply to a chkpth
 ****************************************************************************/
-int reply_chkpth(char *inbuf,char *outbuf)
+int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int outsize = 0;
-  int cnum,mode;
+  int mode;
   pstring name;
   BOOL ok = False;
   BOOL bad_path = False;
+  SMB_STRUCT_STAT st;
  
-  cnum = SVAL(inbuf,smb_tid);
-  
   pstrcpy(name,smb_buf(inbuf) + 1);
-  unix_convert(name,cnum,0,&bad_path);
+  unix_convert(name,conn,0,&bad_path,&st);
 
   mode = SVAL(inbuf,smb_vwv0);
 
-  if (check_name(name,cnum))
-    ok = directory_exist(name,NULL);
+  if (check_name(name,conn)) {
+    if(VALID_STAT(st))
+      ok = S_ISDIR(st.st_mode);
+    else
+      ok = dos_directory_exist(name,NULL);
+  }
 
   if (!ok)
   {
@@ -710,11 +853,11 @@ int reply_chkpth(char *inbuf,char *outbuf)
 
     return(UNIXERROR(ERRDOS,ERRbadpath));
   }
+
   outsize = set_message(outbuf,0,0,True);
-  
-  DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
-  
+
+  DEBUG(3,("chkpth %s mode=%d\n", name, mode));
+
   return(outsize);
 }
 
@@ -722,39 +865,37 @@ int reply_chkpth(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a getatr
 ****************************************************************************/
-int reply_getatr(char *inbuf,char *outbuf)
+int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
-  int cnum;
   int outsize = 0;
-  struct stat sbuf;
+  SMB_STRUCT_STAT sbuf;
   BOOL ok = False;
   int mode=0;
-  uint32 size=0;
+  SMB_OFF_T size=0;
   time_t mtime=0;
   BOOL bad_path = False;
  
-  cnum = SVAL(inbuf,smb_tid);
-
   pstrcpy(fname,smb_buf(inbuf) + 1);
-  unix_convert(fname,cnum,0,&bad_path);
 
   /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
      under WfWg - weird! */
   if (! (*fname))
-    {
-      mode = aHIDDEN | aDIR;
-      if (!CAN_WRITE(cnum)) mode |= aRONLY;
-      size = 0;
-      mtime = 0;
-      ok = True;
-    }
+  {
+    mode = aHIDDEN | aDIR;
+    if (!CAN_WRITE(conn)) mode |= aRONLY;
+    size = 0;
+    mtime = 0;
+    ok = True;
+  }
   else
-    if (check_name(fname,cnum))
+  {
+    unix_convert(fname,conn,0,&bad_path,&sbuf);
+    if (check_name(fname,conn))
     {
-      if (sys_stat(fname,&sbuf) == 0)
+      if (VALID_STAT(sbuf) || conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == 0)
       {
-        mode = dos_mode(cnum,fname,&sbuf);
+        mode = dos_mode(conn,fname,&sbuf);
         size = sbuf.st_size;
         mtime = sbuf.st_mtime;
         if (mode & aDIR)
@@ -764,6 +905,7 @@ int reply_getatr(char *inbuf,char *outbuf)
       else
         DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
     }
+  }
   
   if (!ok)
   {
@@ -779,8 +921,11 @@ int reply_getatr(char *inbuf,char *outbuf)
   outsize = set_message(outbuf,10,0,True);
 
   SSVAL(outbuf,smb_vwv0,mode);
-  put_dos_date3(outbuf,smb_vwv1,mtime);
-  SIVAL(outbuf,smb_vwv3,size);
+  if(lp_dos_filetime_resolution(SNUM(conn)) )
+    put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
+  else
+    put_dos_date3(outbuf,smb_vwv1,mtime);
+  SIVAL(outbuf,smb_vwv3,(uint32)size);
 
   if (Protocol >= PROTOCOL_NT1) {
     char *p = strrchr(fname,'/');
@@ -790,7 +935,7 @@ int reply_getatr(char *inbuf,char *outbuf)
       SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
   }
   
-  DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
+  DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
   
   return(outsize);
 }
@@ -799,30 +944,28 @@ int reply_getatr(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a setatr
 ****************************************************************************/
-int reply_setatr(char *inbuf,char *outbuf)
+int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
-  int cnum;
   int outsize = 0;
   BOOL ok=False;
   int mode;
   time_t mtime;
+  SMB_STRUCT_STAT st;
   BOOL bad_path = False;
  
-  cnum = SVAL(inbuf,smb_tid);
-  
   pstrcpy(fname,smb_buf(inbuf) + 1);
-  unix_convert(fname,cnum,0,&bad_path);
+  unix_convert(fname,conn,0,&bad_path,&st);
 
   mode = SVAL(inbuf,smb_vwv0);
   mtime = make_unix_date3(inbuf+smb_vwv1);
   
-  if (directory_exist(fname,NULL))
+  if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
     mode |= aDIR;
-  if (check_name(fname,cnum))
-    ok =  (dos_chmod(cnum,fname,mode,NULL) == 0);
+  if (check_name(fname,conn))
+    ok =  (file_chmod(conn,fname,mode,NULL) == 0);
   if (ok)
-    ok = set_filetime(cnum,fname,mtime);
+    ok = set_filetime(conn,fname,mtime);
   
   if (!ok)
   {
@@ -837,7 +980,7 @@ int reply_setatr(char *inbuf,char *outbuf)
  
   outsize = set_message(outbuf,0,0,True);
   
-  DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
+  DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
   
   return(outsize);
 }
@@ -846,15 +989,12 @@ int reply_setatr(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a dskattr
 ****************************************************************************/
-int reply_dskattr(char *inbuf,char *outbuf)
+int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum;
   int outsize = 0;
-  int dfree,dsize,bsize;
+  SMB_BIG_UINT dfree,dsize,bsize;
   
-  cnum = SVAL(inbuf,smb_tid);
-  
-  sys_disk_free(".",&bsize,&dfree,&dsize);
+  conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);
   
   outsize = set_message(outbuf,5,0,True);
   
@@ -862,9 +1002,9 @@ int reply_dskattr(char *inbuf,char *outbuf)
   SSVAL(outbuf,smb_vwv1,bsize/512);
   SSVAL(outbuf,smb_vwv2,512);
   SSVAL(outbuf,smb_vwv3,dfree);
-  
-  DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
-  
+
+  DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
+
   return(outsize);
 }
 
@@ -873,15 +1013,15 @@ int reply_dskattr(char *inbuf,char *outbuf)
   reply to a search
   Can be called from SMBsearch, SMBffirst or SMBfunique.
 ****************************************************************************/
-int reply_search(char *inbuf,char *outbuf)
+int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring mask;
   pstring directory;
   pstring fname;
-  int size,mode;
+  SMB_OFF_T size;
+  int mode;
   time_t date;
   int dirtype;
-  int cnum;
   int outsize = 0;
   int numentries = 0;
   BOOL finished = False;
@@ -904,8 +1044,6 @@ int reply_search(char *inbuf,char *outbuf)
   if(CVAL(inbuf,smb_com) == SMBffirst)
     expect_close = True;
   
-  cnum = SVAL(inbuf,smb_tid);
-
   outsize = set_message(outbuf,1,3,True);
   maxentries = SVAL(inbuf,smb_vwv0); 
   dirtype = SVAL(inbuf,smb_vwv1);
@@ -924,16 +1062,16 @@ int reply_search(char *inbuf,char *outbuf)
 
       pstrcpy(directory,smb_buf(inbuf)+1);
       pstrcpy(dir2,smb_buf(inbuf)+1);
-      unix_convert(directory,cnum,0,&bad_path);
+      unix_convert(directory,conn,0,&bad_path,NULL);
       unix_format(dir2);
 
-      if (!check_name(directory,cnum))
+      if (!check_name(directory,conn))
         can_open = False;
 
       p = strrchr(dir2,'/');
       if (p == NULL) 
       {
-        strcpy(mask,dir2);
+        pstrcpy(mask,dir2);
         *dir2 = 0;
       }
       else
@@ -949,7 +1087,7 @@ int reply_search(char *inbuf,char *outbuf)
         *p = 0;
 
       if (strlen(directory) == 0)
-        strcpy(directory,"./");
+        pstrcpy(directory,"./");
       bzero(status,21);
       CVAL(status,0) = dirtype;
     }
@@ -959,10 +1097,10 @@ int reply_search(char *inbuf,char *outbuf)
       memcpy(mask,status+1,11);
       mask[11] = 0;
       dirtype = CVAL(status,0) & 0x1F;
-      Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);      
-      if (!Connections[cnum].dirptr)
+      conn->dirptr = dptr_fetch(status+12,&dptr_num);      
+      if (!conn->dirptr)
        goto SearchEmpty;
-      string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
+      string_set(&conn->dirpath,dptr_path(dptr_num));
       if (!case_sensitive)
        strnorm(mask);
     }
@@ -976,20 +1114,33 @@ int reply_search(char *inbuf,char *outbuf)
        fstrcpy(ext,p+1);
        *p = 0;
        trim_string(mask,NULL," ");
-       strcat(mask,".");
-       strcat(mask,ext);
+       pstrcat(mask,".");
+       pstrcat(mask,ext);
       }
   }
 
+  /* Convert the formatted mask. (This code lives in trans2.c) */
+  mask_convert(mask);
+
   {
-    for (p=mask; *p; p++)
+    int skip;
+    p = mask;
+    while(*p)
+    {
+      if((skip = skip_multibyte_char( *p )) != 0 )
       {
-       if (*p != '?' && *p != '*' && !isdoschar(*p))
-         {
-           DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
-           *p = '?';
-         }
+        p += skip;
+      }
+      else
+      {
+        if (*p != '?' && *p != '*' && !isdoschar(*p))
+        {
+          DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
+          *p = '?';
+        }
+        p++;
       }
+    }
   }
 
   if (!strchr(mask,'.') && strlen(mask)>8)
@@ -998,7 +1149,7 @@ int reply_search(char *inbuf,char *outbuf)
       fstrcpy(tmp,&mask[8]);
       mask[8] = '.';
       mask[9] = 0;
-      strcat(mask,tmp);
+      pstrcat(mask,tmp);
     }
 
   DEBUG(5,("mask=%s directory=%s\n",mask,directory));
@@ -1011,7 +1162,7 @@ int reply_search(char *inbuf,char *outbuf)
       
       if (status_len == 0)
        {
-         dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
+         dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
          if (dptr_num < 0)
         {
           if(dptr_num == -2)
@@ -1034,7 +1185,7 @@ int reply_search(char *inbuf,char *outbuf)
          if ((dirtype&0x1F) == aVOLID)
            {     
              memcpy(p,status,21);
-             make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
+             make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
              dptr_fill(p+12,dptr_num);
              if (dptr_zero(p+12) && (status_len==0))
                numentries = 1;
@@ -1044,15 +1195,16 @@ int reply_search(char *inbuf,char *outbuf)
            }
          else 
            {
-             DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
-             if (in_list(Connections[cnum].dirpath,
-                         lp_dontdescend(SNUM(cnum)),True))
+             DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
+                      conn->dirpath,lp_dontdescend(SNUM(conn))));
+             if (in_list(conn->dirpath,
+                         lp_dontdescend(SNUM(conn)),True))
                check_descend = True;
 
              for (i=numentries;(i<maxentries) && !finished;i++)
                {
                  finished = 
-                   !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
+                   !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
                  if (!finished)
                    {
                      memcpy(p,status,21);
@@ -1105,12 +1257,11 @@ int reply_search(char *inbuf,char *outbuf)
   smb_setlen(outbuf,outsize - 4);
   
   if ((! *directory) && dptr_path(dptr_num))
-    sprintf(directory,"(%s)",dptr_path(dptr_num));
+    slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
 
-  DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
-       timestring(),
+  DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
        smb_fn_name(CVAL(inbuf,smb_com)), 
-       mask,directory,cnum,dirtype,numentries,maxentries));
+       mask, directory, dirtype, numentries, maxentries ) );
 
   return(outsize);
 }
@@ -1119,17 +1270,14 @@ int reply_search(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a fclose (stop directory search)
 ****************************************************************************/
-int reply_fclose(char *inbuf,char *outbuf)
+int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum;
   int outsize = 0;
   int status_len;
   char *path;
   char status[21];
   int dptr_num= -1;
 
-  cnum = SVAL(inbuf,smb_tid);
-
   outsize = set_message(outbuf,1,0,True);
   path = smb_buf(inbuf) + 1;
   status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
@@ -1147,7 +1295,7 @@ int reply_fclose(char *inbuf,char *outbuf)
 
   SSVAL(outbuf,smb_vwv0,0);
 
-  DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
+  DEBUG(3,("search close\n"));
 
   return(outsize);
 }
@@ -1156,51 +1304,47 @@ int reply_fclose(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to an open
 ****************************************************************************/
-int reply_open(char *inbuf,char *outbuf)
+
+int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
-  int cnum;
-  int fnum = -1;
   int outsize = 0;
   int fmode=0;
   int share_mode;
-  int size = 0;
+  SMB_OFF_T size = 0;
   time_t mtime=0;
-  int unixmode;
+  mode_t unixmode;
   int rmode=0;
-  struct stat sbuf;
+  SMB_STRUCT_STAT sbuf;
   BOOL bad_path = False;
   files_struct *fsp;
   int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
  
-  cnum = SVAL(inbuf,smb_tid);
-
   share_mode = SVAL(inbuf,smb_vwv0);
 
   pstrcpy(fname,smb_buf(inbuf)+1);
-  unix_convert(fname,cnum,0,&bad_path);
+  unix_convert(fname,conn,0,&bad_path,NULL);
     
-  fnum = find_free_file();
-  if (fnum < 0)
+  fsp = file_new();
+  if (!fsp)
     return(ERROR(ERRSRV,ERRnofids));
 
-  if (!check_name(fname,cnum))
+  if (!check_name(fname,conn))
   {
     if((errno == ENOENT) && bad_path)
     {
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
-    Files[fnum].reserved = False;
+    file_free(fsp);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
  
-  unixmode = unix_mode(cnum,aARCH);
+  unixmode = unix_mode(conn,aARCH);
       
-  open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
-                   oplock_request,&rmode,NULL);
-
-  fsp = &Files[fnum];
+  open_file_shared(fsp, conn, fname, share_mode,
+                  (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN),
+                  unixmode, oplock_request, &rmode, NULL);
 
   if (!fsp->open)
   {
@@ -1209,33 +1353,36 @@ int reply_open(char *inbuf,char *outbuf)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
-    Files[fnum].reserved = False;
+    file_free(fsp);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
-  if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
-    close_file(fnum,False);
+  if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
+    close_file(fsp,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
     
   size = sbuf.st_size;
-  fmode = dos_mode(cnum,fname,&sbuf);
+  fmode = dos_mode(conn,fname,&sbuf);
   mtime = sbuf.st_mtime;
 
   if (fmode & aDIR) {
     DEBUG(3,("attempt to open a directory %s\n",fname));
-    close_file(fnum,False);
+    close_file(fsp,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
   
   outsize = set_message(outbuf,7,0,True);
-  SSVAL(outbuf,smb_vwv0,fnum);
+  SSVAL(outbuf,smb_vwv0,fsp->fnum);
   SSVAL(outbuf,smb_vwv1,fmode);
-  put_dos_date3(outbuf,smb_vwv2,mtime);
-  SIVAL(outbuf,smb_vwv4,size);
+  if(lp_dos_filetime_resolution(SNUM(conn)) )
+    put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
+  else
+    put_dos_date3(outbuf,smb_vwv2,mtime);
+  SIVAL(outbuf,smb_vwv4,(uint32)size);
   SSVAL(outbuf,smb_vwv6,rmode);
 
-  if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+  if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
     
@@ -1248,11 +1395,9 @@ int reply_open(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to an open and X
 ****************************************************************************/
-int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
+int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
   pstring fname;
-  int cnum = SVAL(inbuf,smb_tid);
-  int fnum = -1;
   int smb_mode = SVAL(inbuf,smb_vwv3);
   int smb_attr = SVAL(inbuf,smb_vwv5);
   /* Breakout the oplock request bits so we can set the
@@ -1266,44 +1411,45 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
 #endif
   int smb_ofun = SVAL(inbuf,smb_vwv8);
-  int unixmode;
-  int size=0,fmode=0,mtime=0,rmode=0;
-  struct stat sbuf;
+  mode_t unixmode;
+  SMB_OFF_T size=0;
+  int fmode=0,mtime=0,rmode=0;
+  SMB_STRUCT_STAT sbuf;
   int smb_action = 0;
   BOOL bad_path = False;
   files_struct *fsp;
 
   /* If it's an IPC, pass off the pipe handler. */
-  if (IS_IPC(cnum))
-    return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
+  if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
+  {
+    return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
+  }
 
   /* XXXX we need to handle passed times, sattr and flags */
 
   pstrcpy(fname,smb_buf(inbuf));
-  unix_convert(fname,cnum,0,&bad_path);
+  unix_convert(fname,conn,0,&bad_path,NULL);
     
-  fnum = find_free_file();
-  if (fnum < 0)
+  fsp = file_new();
+  if (!fsp)
     return(ERROR(ERRSRV,ERRnofids));
 
-  if (!check_name(fname,cnum))
+  if (!check_name(fname,conn))
   {
     if((errno == ENOENT) && bad_path)
     {
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
-    Files[fnum].reserved = False;
+    file_free(fsp);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
-  unixmode = unix_mode(cnum,smb_attr | aARCH);
+  unixmode = unix_mode(conn,smb_attr | aARCH);
       
-  open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
-                  oplock_request, &rmode,&smb_action);
+  open_file_shared(fsp, conn, fname, smb_mode, smb_ofun, unixmode,
+                  oplock_request, &rmode, &smb_action);
       
-  fsp = &Files[fnum];
-
   if (!fsp->open)
   {
     if((errno == ENOENT) && bad_path)
@@ -1311,20 +1457,20 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
-    Files[fnum].reserved = False;
+    file_free(fsp);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
-  if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
-    close_file(fnum,False);
+  if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
+    close_file(fsp,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
 
   size = sbuf.st_size;
-  fmode = dos_mode(cnum,fname,&sbuf);
+  fmode = dos_mode(conn,fname,&sbuf);
   mtime = sbuf.st_mtime;
   if (fmode & aDIR) {
-    close_file(fnum,False);
+    close_file(fsp,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -1333,7 +1479,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
      correct bit for extended oplock reply.
    */
 
-  if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+  if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
     smb_action |= EXTENDED_OPLOCK_GRANTED;
   }
 
@@ -1346,7 +1492,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
      correct bit for core oplock reply.
    */
 
-  if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+  if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
 
@@ -1355,15 +1501,16 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   }
 
   set_message(outbuf,15,0,True);
-  SSVAL(outbuf,smb_vwv2,fnum);
+  SSVAL(outbuf,smb_vwv2,fsp->fnum);
   SSVAL(outbuf,smb_vwv3,fmode);
-  put_dos_date3(outbuf,smb_vwv4,mtime);
-  SIVAL(outbuf,smb_vwv6,size);
+  if(lp_dos_filetime_resolution(SNUM(conn)) )
+    put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
+  else
+    put_dos_date3(outbuf,smb_vwv4,mtime);
+  SIVAL(outbuf,smb_vwv6,(uint32)size);
   SSVAL(outbuf,smb_vwv8,rmode);
   SSVAL(outbuf,smb_vwv11,smb_action);
 
-  chain_fnum = fnum;
-
   return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
@@ -1371,7 +1518,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 /****************************************************************************
   reply to a SMBulogoffX
 ****************************************************************************/
-int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
+int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
   uint16 vuid = SVAL(inbuf,smb_uid);
   user_struct *vuser = get_valid_user_struct(vuid);
@@ -1383,18 +1530,14 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
   /* in user level security we are supposed to close any files
      open by this user */
   if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
-    int i;
-    for (i=0;i<MAX_OPEN_FILES;i++)
-      if (Files[i].uid == vuser->uid && Files[i].open) {
-       close_file(i,False);
-      }
+         file_close_user(vuid);
   }
 
   invalidate_vuid(vuid);
 
   set_message(outbuf,2,0,True);
 
-  DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
+  DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
 
   return chain_reply(inbuf,outbuf,length,bufsize);
 }
@@ -1403,11 +1546,10 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
 /****************************************************************************
   reply to a mknew or a create
 ****************************************************************************/
-int reply_mknew(char *inbuf,char *outbuf)
+int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
-  int cnum,com;
-  int fnum = -1;
+  int com;
   int outsize = 0;
   int createmode;
   mode_t unixmode;
@@ -1417,31 +1559,30 @@ int reply_mknew(char *inbuf,char *outbuf)
   int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
  
   com = SVAL(inbuf,smb_com);
-  cnum = SVAL(inbuf,smb_tid);
 
   createmode = SVAL(inbuf,smb_vwv0);
   pstrcpy(fname,smb_buf(inbuf)+1);
-  unix_convert(fname,cnum,0,&bad_path);
+  unix_convert(fname,conn,0,&bad_path,NULL);
 
   if (createmode & aVOLID)
     {
       DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
     }
   
-  unixmode = unix_mode(cnum,createmode);
+  unixmode = unix_mode(conn,createmode);
   
-  fnum = find_free_file();
-  if (fnum < 0)
+  fsp = file_new();
+  if (!fsp)
     return(ERROR(ERRSRV,ERRnofids));
 
-  if (!check_name(fname,cnum))
+  if (!check_name(fname,conn))
   {
     if((errno == ENOENT) && bad_path)
     {
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
-    Files[fnum].reserved = False;
+    file_free(fsp);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -1457,11 +1598,10 @@ int reply_mknew(char *inbuf,char *outbuf)
   }
 
   /* Open file in dos compatibility share mode. */
-  open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, 
-                   oplock_request, NULL, NULL);
+  open_file_shared(fsp, conn, fname,
+                 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
+                 ofun, unixmode, oplock_request, NULL, NULL);
   
-  fsp = &Files[fnum];
-
   if (!fsp->open)
   {
     if((errno == ENOENT) && bad_path) 
@@ -1469,23 +1609,24 @@ int reply_mknew(char *inbuf,char *outbuf)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
-    Files[fnum].reserved = False;
+    file_free(fsp);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
  
   outsize = set_message(outbuf,1,0,True);
-  SSVAL(outbuf,smb_vwv0,fnum);
+  SSVAL(outbuf,smb_vwv0,fsp->fnum);
 
-  if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+  if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
  
   if(fsp->granted_oplock)
     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
  
-  DEBUG(2,("new file %s\n",fname));
-  DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
-  
+  DEBUG( 2, ( "new file %s\n", fname ) );
+  DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
+        fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
+
   return(outsize);
 }
 
@@ -1493,12 +1634,10 @@ int reply_mknew(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a create temporary file
 ****************************************************************************/
-int reply_ctemp(char *inbuf,char *outbuf)
+int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
   pstring fname2;
-  int cnum;
-  int fnum = -1;
   int outsize = 0;
   int createmode;
   mode_t unixmode;
@@ -1506,37 +1645,36 @@ int reply_ctemp(char *inbuf,char *outbuf)
   files_struct *fsp;
   int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
  
-  cnum = SVAL(inbuf,smb_tid);
   createmode = SVAL(inbuf,smb_vwv0);
   pstrcpy(fname,smb_buf(inbuf)+1);
-  strcat(fname,"/TMXXXXXX");
-  unix_convert(fname,cnum,0,&bad_path);
+  pstrcat(fname,"/TMXXXXXX");
+  unix_convert(fname,conn,0,&bad_path,NULL);
   
-  unixmode = unix_mode(cnum,createmode);
+  unixmode = unix_mode(conn,createmode);
   
-  fnum = find_free_file();
-  if (fnum < 0)
+  fsp = file_new();
+  if (fsp)
     return(ERROR(ERRSRV,ERRnofids));
 
-  if (!check_name(fname,cnum))
+  if (!check_name(fname,conn))
   {
     if((errno == ENOENT) && bad_path)
     {
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
-    Files[fnum].reserved = False;
+    file_free(fsp);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
-  strcpy(fname2,(char *)mktemp(fname));
+  pstrcpy(fname2,(char *)mktemp(fname));
 
   /* Open file in dos compatibility share mode. */
   /* We should fail if file exists. */
-  open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, 
-                   oplock_request, NULL, NULL);
-
-  fsp = &Files[fnum];
+  open_file_shared(fsp,conn,fname2,
+                  SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
+                  (FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_FAIL), 
+                  unixmode, oplock_request, NULL, NULL);
 
   if (!fsp->open)
   {
@@ -1545,25 +1683,26 @@ int reply_ctemp(char *inbuf,char *outbuf)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
-    Files[fnum].reserved = False;
+    file_free(fsp);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
   outsize = set_message(outbuf,1,2 + strlen(fname2),True);
-  SSVAL(outbuf,smb_vwv0,fnum);
+  SSVAL(outbuf,smb_vwv0,fsp->fnum);
   CVAL(smb_buf(outbuf),0) = 4;
-  strcpy(smb_buf(outbuf) + 1,fname2);
+  pstrcpy(smb_buf(outbuf) + 1,fname2);
 
-  if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+  if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
   
   if(fsp->granted_oplock)
     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
 
-  DEBUG(2,("created temp file %s\n",fname2));
-  DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
-  
+  DEBUG( 2, ( "created temp file %s\n", fname2 ) );
+  DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
+        fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
+
   return(outsize);
 }
 
@@ -1571,33 +1710,32 @@ int reply_ctemp(char *inbuf,char *outbuf)
 /*******************************************************************
 check if a user is allowed to delete a file
 ********************************************************************/
-static BOOL can_delete(char *fname,int cnum,int dirtype)
+static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
 {
-  struct stat sbuf;
+  SMB_STRUCT_STAT sbuf;
   int fmode;
 
-  if (!CAN_WRITE(cnum)) return(False);
+  if (!CAN_WRITE(conn)) return(False);
 
-  if (sys_lstat(fname,&sbuf) != 0) return(False);
-  fmode = dos_mode(cnum,fname,&sbuf);
+  if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False);
+  fmode = dos_mode(conn,fname,&sbuf);
   if (fmode & aDIR) return(False);
-  if (!lp_delete_readonly(SNUM(cnum))) {
+  if (!lp_delete_readonly(SNUM(conn))) {
     if (fmode & aRONLY) return(False);
   }
   if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
     return(False);
-  if (!check_file_sharing(cnum,fname,False)) return(False);
+  if (!check_file_sharing(conn,fname,False)) return(False);
   return(True);
 }
 
 /****************************************************************************
   reply to a unlink
 ****************************************************************************/
-int reply_unlink(char *inbuf,char *outbuf)
+int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int outsize = 0;
   pstring name;
-  int cnum;
   int dirtype;
   pstring directory;
   pstring mask;
@@ -1610,41 +1748,42 @@ int reply_unlink(char *inbuf,char *outbuf)
 
   *directory = *mask = 0;
 
-  cnum = SVAL(inbuf,smb_tid);
   dirtype = SVAL(inbuf,smb_vwv0);
   
   pstrcpy(name,smb_buf(inbuf) + 1);
    
   DEBUG(3,("reply_unlink : %s\n",name));
    
-  unix_convert(name,cnum,0,&bad_path);
+  unix_convert(name,conn,0,&bad_path,NULL);
 
   p = strrchr(name,'/');
   if (!p) {
-    strcpy(directory,"./");
-    strcpy(mask,name);
+    pstrcpy(directory,"./");
+    pstrcpy(mask,name);
   } else {
     *p = 0;
-    strcpy(directory,name);
-    strcpy(mask,p+1);
+    pstrcpy(directory,name);
+    pstrcpy(mask,p+1);
   }
 
   if (is_mangled(mask))
-    check_mangled_stack(mask);
+    check_mangled_cache( mask );
 
   has_wild = strchr(mask,'*') || strchr(mask,'?');
 
   if (!has_wild) {
-    strcat(directory,"/");
-    strcat(directory,mask);
-    if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
-    if (!count) exists = file_exist(directory,NULL);    
+    pstrcat(directory,"/");
+    pstrcat(directory,mask);
+    if (can_delete(directory,conn,dirtype) && !conn->vfs_ops.unlink(directory))
+      count++;
+    if (!count)
+      exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);    
   } else {
     void *dirptr = NULL;
     char *dname;
 
-    if (check_name(directory,cnum))
-      dirptr = OpenDir(cnum, directory, True);
+    if (check_name(directory,conn))
+      dirptr = OpenDir(conn, directory, True);
 
     /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
        the pattern matches against the long name, otherwise the short name 
@@ -1656,7 +1795,7 @@ int reply_unlink(char *inbuf,char *outbuf)
        error = ERRbadfile;
 
        if (strequal(mask,"????????.???"))
-         strcpy(mask,"*");
+         pstrcpy(mask,"*");
 
        while ((dname = ReadDirName(dirptr)))
          {
@@ -1666,9 +1805,9 @@ int reply_unlink(char *inbuf,char *outbuf)
            if(!mask_match(fname, mask, case_sensitive, False)) continue;
 
            error = ERRnoaccess;
-           sprintf(fname,"%s/%s",directory,dname);
-           if (!can_delete(fname,cnum,dirtype)) continue;
-           if (!sys_unlink(fname)) count++;
+           slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+           if (!can_delete(fname,conn,dirtype)) continue;
+           if (!conn->vfs_ops.unlink(fname)) count++;
            DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
          }
        CloseDir(dirptr);
@@ -1698,15 +1837,14 @@ int reply_unlink(char *inbuf,char *outbuf)
 /****************************************************************************
    reply to a readbraw (core+ protocol)
 ****************************************************************************/
-int reply_readbraw(char *inbuf, char *outbuf)
+int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,maxcount,mincount,fnum;
-  int nread = 0;
-  uint32 startpos;
+  size_t maxcount,mincount;
+  size_t nread = 0;
+  SMB_OFF_T startpos;
   char *header = outbuf;
-  int ret=0;
-  int fd;
-  char *fname;
+  ssize_t ret=0;
+  files_struct *fsp;
 
   /*
    * Special check if an oplock break has been issued
@@ -1717,88 +1855,103 @@ int reply_readbraw(char *inbuf, char *outbuf)
   if(global_oplock_break)
   {
     _smb_setlen(header,0);
-    transfer_file(0,Client,0,header,4,0);
+    transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
     DEBUG(5,("readbraw - oplock break finished\n"));
     return -1;
   }
 
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
+  fsp = file_fsp(inbuf,smb_vwv0);
 
   startpos = IVAL(inbuf,smb_vwv1);
-  maxcount = SVAL(inbuf,smb_vwv3);
-  mincount = SVAL(inbuf,smb_vwv4);
+#ifdef LARGE_SMB_OFF_T
+  if(CVAL(inbuf,smb_wct) == 10) {
+    /*
+     * This is a large offset (64 bit) read.
+     */
+    startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
+    if(startpos < 0) {
+      DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
+            (double)startpos ));
+         _smb_setlen(header,0);
+         transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
+         return(-1);
+    }      
+  }
+#endif /* LARGE_SMB_OFF_T */
+  maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
+  mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
 
   /* ensure we don't overrun the packet size */
   maxcount = MIN(65535,maxcount);
   maxcount = MAX(mincount,maxcount);
 
-  if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
-    {
-      DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
-      _smb_setlen(header,0);
-      transfer_file(0,Client,0,header,4,0);
-      return(-1);
-    }
-  else
-    {
-      fd = Files[fnum].fd_ptr->fd;
-      fname = Files[fnum].name;
-    }
-
+  if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
+         DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
+         _smb_setlen(header,0);
+         transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
+         return(-1);
+  }
 
-  if (!is_locked(fnum,cnum,maxcount,startpos))
-    {
-      int size = Files[fnum].size;
-      int sizeneeded = startpos + maxcount;
+  if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
+  {
+    SMB_OFF_T size = fsp->size;
+    SMB_OFF_T sizeneeded = startpos + maxcount;
            
-      if (size < sizeneeded) {
-       struct stat st;
-       if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
-         size = st.st_size;
-       if (!Files[fnum].can_write) 
-         Files[fnum].size = size;
-      }
-
-      nread = MIN(maxcount,(int)(size - startpos));      
+    if (size < sizeneeded)
+    {
+      SMB_STRUCT_STAT st;
+      if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0)
+        size = st.st_size;
+      if (!fsp->can_write) 
+        fsp->size = size;
     }
 
+    nread = MIN(maxcount,(size - startpos));     
+  }
+
   if (nread < mincount)
     nread = 0;
   
-  DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
-          timestring(),
-          fnum,cnum,startpos,
-          maxcount,mincount,nread));
+  DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
+             fsp->fnum, (double)startpos,
+             maxcount, mincount, nread ) );
   
 #if UNSAFE_READRAW
   {
+    BOOL seek_fail = False;
     int predict=0;
     _smb_setlen(header,nread);
 
 #if USE_READ_PREDICTION
-    if (!Files[fnum].can_write)
-      predict = read_predict(fd,startpos,header+4,NULL,nread);
-#endif
+    if (!fsp->can_write)
+      predict = read_predict(fsp, fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
+#endif /* USE_READ_PREDICTION */
+
+    if ((nread-predict) > 0) {
+      if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) {
+        DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
+        ret = 0;
+        seek_fail = True;
+      } 
+    }
 
-    if ((nread-predict) > 0)
-      seek_file(fnum,startpos + predict);
-    
-    ret = transfer_file(fd,Client,nread-predict,header,4+predict,
-                       startpos+predict);
+    if(!seek_fail)
+      ret = (ssize_t)vfs_transfer_file(-1, fsp->fd_ptr->fd, Client, NULL,
+                                   (SMB_OFF_T)(nread-predict),header,4+predict, 
+                                   startpos+predict);
   }
 
   if (ret != nread+4)
     DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
-            fname,startpos,nread,ret));
+            fsp->fsp_name,startpos,nread,ret));
 
-#else
-  ret = read_file(fnum,header+4,startpos,nread);
+#else /* UNSAFE_READRAW */
+  ret = read_file(fsp,header+4,startpos,nread);
   if (ret < mincount) ret = 0;
 
   _smb_setlen(header,ret);
   transfer_file(0,Client,0,header,4+ret,0);
-#endif
+#endif /* UNSAFE_READRAW */
 
   DEBUG(5,("readbraw finished\n"));
   return -1;
@@ -1808,22 +1961,20 @@ int reply_readbraw(char *inbuf, char *outbuf)
 /****************************************************************************
   reply to a lockread (core+ protocol)
 ****************************************************************************/
-int reply_lockread(char *inbuf,char *outbuf)
+int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
 {
-  int cnum,fnum;
-  int nread = -1;
+  ssize_t nread = -1;
   char *data;
   int outsize = 0;
-  uint32 startpos, numtoread;
+  SMB_OFF_T startpos;
+  size_t numtoread;
   int eclass;
   uint32 ecode;
-  
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
-  CHECK_FNUM(fnum,cnum);
-  CHECK_READ(fnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_READ(fsp);
+  CHECK_ERROR(fsp);
 
   numtoread = SVAL(inbuf,smb_vwv1);
   startpos = IVAL(inbuf,smb_vwv2);
@@ -1832,21 +1983,32 @@ int reply_lockread(char *inbuf,char *outbuf)
   numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
   data = smb_buf(outbuf) + 3;
   
-  if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
+  if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
+    if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
+      /*
+       * A blocking lock was requested. Package up
+       * this smb into a queued request and push it
+       * onto the blocking lock queue.
+       */
+      if(push_blocking_lock_request(inbuf, length, -1, 0))
+        return -1;
+    }
     return (ERROR(eclass,ecode));
+  }
+
+  nread = read_file(fsp,data,startpos,numtoread);
 
-  nread = read_file(fnum,data,startpos,numtoread);
-  
   if (nread < 0)
     return(UNIXERROR(ERRDOS,ERRnoaccess));
-  
+
   outsize += nread;
   SSVAL(outbuf,smb_vwv0,nread);
   SSVAL(outbuf,smb_vwv5,nread+3);
   SSVAL(smb_buf(outbuf),1,nread);
-  
-  DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
-  
+
+  DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
+            fsp->fnum, numtoread, nread ) );
+
   return(outsize);
 }
 
@@ -1854,20 +2016,18 @@ int reply_lockread(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a read
 ****************************************************************************/
-int reply_read(char *inbuf,char *outbuf)
+int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,numtoread,fnum;
-  int nread = 0;
+  size_t numtoread;
+  ssize_t nread = 0;
   char *data;
-  uint32 startpos;
+  SMB_OFF_T startpos;
   int outsize = 0;
-  
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
-  CHECK_FNUM(fnum,cnum);
-  CHECK_READ(fnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_READ(fsp);
+  CHECK_ERROR(fsp);
 
   numtoread = SVAL(inbuf,smb_vwv1);
   startpos = IVAL(inbuf,smb_vwv2);
@@ -1876,11 +2036,12 @@ int reply_read(char *inbuf,char *outbuf)
   numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
   data = smb_buf(outbuf) + 3;
   
-  if (is_locked(fnum,cnum,numtoread,startpos))
+  if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
     return(ERROR(ERRDOS,ERRlock));     
 
-  if (numtoread > 0)
-    nread = read_file(fnum,data,startpos,numtoread);
+  if (numtoread > 0) {
+    nread = read_file(fsp,data,startpos,numtoread);
+  }
   
   if (nread < 0)
     return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -1891,8 +2052,9 @@ int reply_read(char *inbuf,char *outbuf)
   CVAL(smb_buf(outbuf),0) = 1;
   SSVAL(smb_buf(outbuf),1,nread);
   
-  DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
-  
+  DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
+            fsp->fnum, numtoread, nread ) );
+
   return(outsize);
 }
 
@@ -1900,69 +2062,70 @@ int reply_read(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a read and X
 ****************************************************************************/
-int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
+int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
-  int fnum = GETFNUM(inbuf,smb_vwv2);
-  uint32 smb_offs = IVAL(inbuf,smb_vwv3);
-  int smb_maxcnt = SVAL(inbuf,smb_vwv5);
-  int smb_mincnt = SVAL(inbuf,smb_vwv6);
-  int cnum;
-  int nread = -1;
+  files_struct *fsp = file_fsp(inbuf,smb_vwv2);
+  SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
+  size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
+  size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
+  ssize_t nread = -1;
   char *data;
-  BOOL ok = False;
 
-  cnum = SVAL(inbuf,smb_tid);
+  /* If it's an IPC, pass off the pipe handler. */
+  if (IS_IPC(conn))
+    return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
 
-  CHECK_FNUM(fnum,cnum);
-  CHECK_READ(fnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_READ(fsp);
+  CHECK_ERROR(fsp);
 
   set_message(outbuf,12,0,True);
   data = smb_buf(outbuf);
 
-  if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
+#ifdef LARGE_SMB_OFF_T
+  if(CVAL(inbuf,smb_wct) == 12) {
+    /*
+     * This is a large offset (64 bit) read.
+     */
+    startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
+  }
+#endif /* LARGE_SMB_OFF_T */
+
+  if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
     return(ERROR(ERRDOS,ERRlock));
-  nread = read_file(fnum,data,smb_offs,smb_maxcnt);
-  ok = True;
-  
+  nread = read_file(fsp,data,startpos,smb_maxcnt);
+
   if (nread < 0)
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   
   SSVAL(outbuf,smb_vwv5,nread);
   SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
   SSVAL(smb_buf(outbuf),-2,nread);
-  
-  DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
-       timestring(),fnum,cnum,
-       smb_mincnt,smb_maxcnt,nread));
 
-  chain_fnum = fnum;
+  DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
+             fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
 
   return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
-
 /****************************************************************************
   reply to a writebraw (core+ or LANMAN1.0 protocol)
 ****************************************************************************/
-int reply_writebraw(char *inbuf,char *outbuf)
+int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int nwritten=0;
-  int total_written=0;
-  int numtowrite=0;
-  int cnum,fnum;
-  int outsize = 0;
-  long startpos;
+  ssize_t nwritten=0;
+  ssize_t total_written=0;
+  size_t numtowrite=0;
+  size_t tcount;
+  SMB_OFF_T startpos;
   char *data=NULL;
   BOOL write_through;
-  int tcount;
-
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+  int outsize = 0;
 
-  CHECK_FNUM(fnum,cnum);
-  CHECK_WRITE(fnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_WRITE(fsp);
+  CHECK_ERROR(fsp);
   
   tcount = IVAL(inbuf,smb_vwv1);
   startpos = IVAL(inbuf,smb_vwv3);
@@ -1982,17 +2145,19 @@ int reply_writebraw(char *inbuf,char *outbuf)
   CVAL(inbuf,smb_com) = SMBwritec;
   CVAL(outbuf,smb_com) = SMBwritec;
 
-  if (is_locked(fnum,cnum,tcount,startpos))
+  if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
     return(ERROR(ERRDOS,ERRlock));
 
-  if (seek_file(fnum,startpos) != startpos)
-    DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
+  if (seek_file(fsp,startpos) == -1) {
+    DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
+    return(UNIXERROR(ERRDOS,ERRnoaccess));
+  }
 
   if (numtowrite>0)
-    nwritten = write_file(fnum,data,numtowrite);
+    nwritten = write_file(fsp,data,numtowrite);
   
-  DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
-          timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
+  DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
+          fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
 
   if (nwritten < numtowrite) 
     return(UNIXERROR(ERRHRD,ERRdiskfull));
@@ -2020,8 +2185,9 @@ int reply_writebraw(char *inbuf,char *outbuf)
             tcount,nwritten,numtowrite));
   }
 
-  nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
-                          startpos+nwritten);
+  nwritten = vfs_transfer_file(Client, NULL, -1, fsp,
+                              (SMB_OFF_T)numtowrite,NULL,0, 
+                              startpos+nwritten);
   total_written += nwritten;
   
   /* Set up outbuf to return the correct return */
@@ -2029,16 +2195,16 @@ int reply_writebraw(char *inbuf,char *outbuf)
   CVAL(outbuf,smb_com) = SMBwritec;
   SSVAL(outbuf,smb_vwv0,total_written);
 
-  if (nwritten < numtowrite) {
+  if (nwritten < (ssize_t)numtowrite) {
     CVAL(outbuf,smb_rcls) = ERRHRD;
     SSVAL(outbuf,smb_err,ERRdiskfull);      
   }
 
-  if (lp_syncalways(SNUM(cnum)) || write_through)
-    sync_file(fnum);
+  if (lp_syncalways(SNUM(conn)) || write_through)
+    conn->vfs_ops.sync(conn, fsp);
 
-  DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
-          timestring(),fnum,cnum,startpos,numtowrite,total_written));
+  DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
+          fsp->fnum, (double)startpos, numtowrite, total_written));
 
   /* we won't return a status if write through is not selected - this 
      follows what WfWg does */
@@ -2048,35 +2214,33 @@ int reply_writebraw(char *inbuf,char *outbuf)
   return(outsize);
 }
 
-
 /****************************************************************************
   reply to a writeunlock (core+)
 ****************************************************************************/
-int reply_writeunlock(char *inbuf,char *outbuf)
+int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,fnum;
-  int nwritten = -1;
-  int outsize = 0;
+  ssize_t nwritten = -1;
+  size_t numtowrite;
+  SMB_OFF_T startpos;
   char *data;
-  uint32 numtowrite,startpos;
   int eclass;
   uint32 ecode;
-  
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+  int outsize = 0;
 
-  CHECK_FNUM(fnum,cnum);
-  CHECK_WRITE(fnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_WRITE(fsp);
+  CHECK_ERROR(fsp);
 
   numtowrite = SVAL(inbuf,smb_vwv1);
   startpos = IVAL(inbuf,smb_vwv2);
   data = smb_buf(inbuf) + 3;
   
-  if (is_locked(fnum,cnum,numtowrite,startpos))
+  if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
     return(ERROR(ERRDOS,ERRlock));
 
-  seek_file(fnum,startpos);
+  if(seek_file(fsp,startpos) == -1)
+    return(UNIXERROR(ERRDOS,ERRnoaccess));
 
   /* The special X/Open SMB protocol handling of
      zero length writes is *NOT* done for
@@ -2084,68 +2248,63 @@ int reply_writeunlock(char *inbuf,char *outbuf)
   if(numtowrite == 0)
     nwritten = 0;
   else
-    nwritten = write_file(fnum,data,numtowrite);
+    nwritten = write_file(fsp,data,numtowrite);
   
-  if (lp_syncalways(SNUM(cnum)))
-    sync_file(fnum);
+  if (lp_syncalways(SNUM(conn)))
+    conn->vfs_ops.sync(conn, fsp);
 
   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
     return(UNIXERROR(ERRDOS,ERRnoaccess));
 
-  if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
+  if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
     return(ERROR(eclass,ecode));
 
   outsize = set_message(outbuf,1,0,True);
   
   SSVAL(outbuf,smb_vwv0,nwritten);
   
-  DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
-          timestring(),fnum,cnum,numtowrite,nwritten));
-  
+  DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
+             fsp->fnum, numtowrite, nwritten ) );
+
   return(outsize);
 }
 
-
 /****************************************************************************
   reply to a write
 ****************************************************************************/
-int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
+int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
 {
-  int cnum,numtowrite,fnum;
-  int nwritten = -1;
-  int outsize = 0;
-  int startpos;
+  size_t numtowrite;
+  ssize_t nwritten = -1;
+  SMB_OFF_T startpos;
   char *data;
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+  int outsize = 0;
 
-  dum1 = dum2 = 0;
-
-  
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
-
-  CHECK_FNUM(fnum,cnum);
-  CHECK_WRITE(fnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_WRITE(fsp);
+  CHECK_ERROR(fsp);
 
   numtowrite = SVAL(inbuf,smb_vwv1);
   startpos = IVAL(inbuf,smb_vwv2);
   data = smb_buf(inbuf) + 3;
   
-  if (is_locked(fnum,cnum,numtowrite,startpos))
+  if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
     return(ERROR(ERRDOS,ERRlock));
 
-  seek_file(fnum,startpos);
+  if(seek_file(fsp,startpos) == -1)
+    return(UNIXERROR(ERRDOS,ERRnoaccess));
 
   /* X/Open SMB protocol says that if smb_vwv1 is
      zero then the file size should be extended or
      truncated to the size given in smb_vwv[2-3] */
   if(numtowrite == 0)
-    nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
+    nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
   else
-    nwritten = write_file(fnum,data,numtowrite);
+    nwritten = write_file(fsp,data,numtowrite);
   
-  if (lp_syncalways(SNUM(cnum)))
-    sync_file(fnum);
+  if (lp_syncalways(SNUM(conn)))
+    conn->vfs_ops.sync(conn, fsp);
 
   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
     return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -2154,13 +2313,14 @@ int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
   
   SSVAL(outbuf,smb_vwv0,nwritten);
 
-  if (nwritten < numtowrite) {
+  if (nwritten < (ssize_t)numtowrite) {
     CVAL(outbuf,smb_rcls) = ERRHRD;
     SSVAL(outbuf,smb_err,ERRdiskfull);      
   }
   
-  DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
-  
+  DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
+          fsp->fnum, numtowrite, nwritten));
+
   return(outsize);
 }
 
@@ -2168,57 +2328,67 @@ int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
 /****************************************************************************
   reply to a write and X
 ****************************************************************************/
-int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
+int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
-  int fnum = GETFNUM(inbuf,smb_vwv2);
-  uint32 smb_offs = IVAL(inbuf,smb_vwv3);
-  int smb_dsize = SVAL(inbuf,smb_vwv10);
-  int smb_doff = SVAL(inbuf,smb_vwv11);
+  files_struct *fsp = file_fsp(inbuf,smb_vwv2);
+  SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
+  size_t numtowrite = SVAL(inbuf,smb_vwv10);
   BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
-  int cnum;
-  int nwritten = -1;
+  ssize_t nwritten = -1;
+  int smb_doff = SVAL(inbuf,smb_vwv11);
   char *data;
 
-  cnum = SVAL(inbuf,smb_tid);
+  /* If it's an IPC, pass off the pipe handler. */
+  if (IS_IPC(conn))
+    return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
 
-  CHECK_FNUM(fnum,cnum);
-  CHECK_WRITE(fnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_WRITE(fsp);
+  CHECK_ERROR(fsp);
 
   data = smb_base(inbuf) + smb_doff;
 
-  if (is_locked(fnum,cnum,smb_dsize,smb_offs))
+#ifdef LARGE_SMB_OFF_T
+  if(CVAL(inbuf,smb_wct) == 14) {
+    /*
+     * This is a large offset (64 bit) write.
+     */
+    startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
+  }
+#endif /* LARGE_SMB_OFF_T */
+
+  if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
     return(ERROR(ERRDOS,ERRlock));
 
-  seek_file(fnum,smb_offs);
+  if(seek_file(fsp,startpos) == -1)
+    return(UNIXERROR(ERRDOS,ERRnoaccess));
   
   /* X/Open SMB protocol says that, unlike SMBwrite
      if the length is zero then NO truncation is
      done, just a write of zero. To truncate a file,
      use SMBwrite. */
-  if(smb_dsize == 0)
+  if(numtowrite == 0)
     nwritten = 0;
   else
-    nwritten = write_file(fnum,data,smb_dsize);
+    nwritten = write_file(fsp,data,numtowrite);
   
-  if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
+  if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
     return(UNIXERROR(ERRDOS,ERRnoaccess));
 
   set_message(outbuf,6,0,True);
   
   SSVAL(outbuf,smb_vwv2,nwritten);
   
-  if (nwritten < smb_dsize) {
+  if (nwritten < (ssize_t)numtowrite) {
     CVAL(outbuf,smb_rcls) = ERRHRD;
     SSVAL(outbuf,smb_err,ERRdiskfull);      
   }
 
-  DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
-
-  chain_fnum = fnum;
+  DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
+          fsp->fnum, numtowrite, nwritten));
 
-  if (lp_syncalways(SNUM(cnum)) || write_through)
-    sync_file(fnum);
+  if (lp_syncalways(SNUM(conn)) || write_through)
+    conn->vfs_ops.sync(conn, fsp);
 
   return chain_reply(inbuf,outbuf,length,bufsize);
 }
@@ -2227,71 +2397,63 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 /****************************************************************************
   reply to a lseek
 ****************************************************************************/
-int reply_lseek(char *inbuf,char *outbuf)
+int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,fnum;
-  uint32 startpos;
-  int32 res= -1;
+  SMB_OFF_T startpos;
+  SMB_OFF_T res= -1;
   int mode,umode;
   int outsize = 0;
-  
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
-  CHECK_FNUM(fnum,cnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_ERROR(fsp);
 
   mode = SVAL(inbuf,smb_vwv1) & 3;
   startpos = IVAL(inbuf,smb_vwv2);
 
   switch (mode & 3) 
-    {
+  {
     case 0: umode = SEEK_SET; break;
     case 1: umode = SEEK_CUR; break;
     case 2: umode = SEEK_END; break;
     default:
       umode = SEEK_SET; break;
-    }
-  
-  res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
-  Files[fnum].pos = res;
+  }
+
+  if((res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
+    return(UNIXERROR(ERRDOS,ERRnoaccess));
+
+  fsp->pos = res;
   
   outsize = set_message(outbuf,2,0,True);
   SIVALS(outbuf,smb_vwv0,res);
   
-  DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
-  
+  DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
+          fsp->fnum, (double)startpos, mode));
+
   return(outsize);
 }
 
-
 /****************************************************************************
   reply to a flush
 ****************************************************************************/
-int reply_flush(char *inbuf,char *outbuf)
+int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum, fnum;
   int outsize = set_message(outbuf,0,0,True);
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
-
-  if (fnum != 0xFFFF) {
-    CHECK_FNUM(fnum,cnum);
-    CHECK_ERROR(fnum);
+  if (fsp) {
+         CHECK_FSP(fsp,conn);
+         CHECK_ERROR(fsp);
   }
 
-  if (fnum == 0xFFFF)
-    {
-      int i;
-      for (i=0;i<MAX_OPEN_FILES;i++)
-       if (OPEN_FNUM(i))
-         sync_file(i);
-    }
-  else
-    sync_file(fnum);
+  if (!fsp) {
+         file_sync_all(conn);
+  } else {
+         conn->vfs_ops.sync(conn, fsp);
+  }
 
-  DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
+  DEBUG(3,("flush\n"));
   return(outsize);
 }
 
@@ -2299,163 +2461,199 @@ int reply_flush(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a exit
 ****************************************************************************/
-int reply_exit(char *inbuf,char *outbuf)
+int reply_exit(connection_struct *conn, 
+              char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int outsize = set_message(outbuf,0,0,True);
-  DEBUG(3,("%s exit\n",timestring()));
-  
-  return(outsize);
+       int outsize = set_message(outbuf,0,0,True);
+       DEBUG(3,("exit\n"));
+
+       return(outsize);
 }
 
 
 /****************************************************************************
-  reply to a close
+ Reply to a close - has to deal with closing a directory opened by NT SMB's.
 ****************************************************************************/
-int reply_close(char *inbuf,char *outbuf)
+int reply_close(connection_struct *conn,
+               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int fnum,cnum;
-  int outsize = 0;
-  time_t mtime;
-  int32 eclass = 0, err = 0;
+       int outsize = 0;
+       time_t mtime;
+       int32 eclass = 0, err = 0;
+       files_struct *fsp = NULL;
 
-  outsize = set_message(outbuf,0,0,True);
-
-  cnum = SVAL(inbuf,smb_tid);
+       outsize = set_message(outbuf,0,0,True);
 
-  /* If it's an IPC, pass off to the pipe handler. */
-  if (IS_IPC(cnum))
-    return reply_pipe_close(inbuf,outbuf);
+       /* If it's an IPC, pass off to the pipe handler. */
+       if (IS_IPC(conn)) {
+               return reply_pipe_close(conn, inbuf,outbuf);
+       }
 
-  fnum = GETFNUM(inbuf,smb_vwv0);
+       fsp = file_fsp(inbuf,smb_vwv0);
 
-  CHECK_FNUM(fnum,cnum);
+       /*
+        * We can only use CHECK_FSP if we know it's not a directory.
+        */
 
-  if(HAS_CACHED_ERROR(fnum)) {
-    eclass = Files[fnum].wbmpx_ptr->wr_errclass;
-    err = Files[fnum].wbmpx_ptr->wr_error;
-  }
+    if(!fsp || !fsp->open || (fsp->conn != conn))
+      return(ERROR(ERRDOS,ERRbadfid));
 
-  mtime = make_unix_date3(inbuf+smb_vwv1);
+       if(HAS_CACHED_ERROR(fsp)) {
+               eclass = fsp->wbmpx_ptr->wr_errclass;
+               err = fsp->wbmpx_ptr->wr_error;
+       }
 
-  /* try and set the date */
-  set_filetime(cnum, Files[fnum].name,mtime);
+       if(fsp->is_directory) {
+               /*
+                * Special case - close NT SMB directory
+                * handle.
+                */
+               DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
+               close_directory(fsp);
+       } else {
+               /*
+                * Close ordinary file.
+                */
+
+               /*
+                * If there was a modify time outstanding,
+                * try and set it here.
+                */
+               if(fsp->pending_modtime)
+                       set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
+
+               /*
+                * Now take care of any time sent in the close.
+                */
+               mtime = make_unix_date3(inbuf+smb_vwv1);
+               
+               /* try and set the date */
+               set_filetime(conn, fsp->fsp_name,mtime);
 
-  close_file(fnum,True);
+               DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
+                        fsp->fd_ptr->fd, fsp->fnum,
+                        conn->num_files_open));
+  
+               close_file(fsp,True);
+       }  
 
-  /* We have a cached error */
-  if(eclass || err)
-    return(ERROR(eclass,err));
+       /* We have a cached error */
+       if(eclass || err)
+               return(ERROR(eclass,err));
 
-  DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
-          timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
-          Connections[cnum].num_files_open));
-  
-  return(outsize);
+       return(outsize);
 }
 
 
 /****************************************************************************
   reply to a writeclose (Core+ protocol)
 ****************************************************************************/
-int reply_writeclose(char *inbuf,char *outbuf)
+int reply_writeclose(connection_struct *conn,
+                    char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,numtowrite,fnum;
-  int nwritten = -1;
-  int outsize = 0;
-  int startpos;
-  char *data;
-  time_t mtime;
-  
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
-
-  CHECK_FNUM(fnum,cnum);
-  CHECK_WRITE(fnum);
-  CHECK_ERROR(fnum);
-
-  numtowrite = SVAL(inbuf,smb_vwv1);
-  startpos = IVAL(inbuf,smb_vwv2);
-  mtime = make_unix_date3(inbuf+smb_vwv4);
-  data = smb_buf(inbuf) + 1;
-  
-  if (is_locked(fnum,cnum,numtowrite,startpos))
-    return(ERROR(ERRDOS,ERRlock));
+       size_t numtowrite;
+       ssize_t nwritten = -1;
+       int outsize = 0;
+       SMB_OFF_T startpos;
+       char *data;
+       time_t mtime;
+       files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+
+       CHECK_FSP(fsp,conn);
+       CHECK_WRITE(fsp);
+       CHECK_ERROR(fsp);
+
+       numtowrite = SVAL(inbuf,smb_vwv1);
+       startpos = IVAL(inbuf,smb_vwv2);
+       mtime = make_unix_date3(inbuf+smb_vwv4);
+       data = smb_buf(inbuf) + 1;
+  
+       if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
+               return(ERROR(ERRDOS,ERRlock));
       
-  seek_file(fnum,startpos);
+       if(seek_file(fsp,startpos) == -1)
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
       
-  nwritten = write_file(fnum,data,numtowrite);
+       nwritten = write_file(fsp,data,numtowrite);
 
-  set_filetime(cnum, Files[fnum].name,mtime);
+       set_filetime(conn, fsp->fsp_name,mtime);
   
-  close_file(fnum,True);
+       close_file(fsp,True);
 
-  DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
-          timestring(),fnum,cnum,numtowrite,nwritten,
-          Connections[cnum].num_files_open));
+       DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
+                fsp->fnum, numtowrite, nwritten,
+                conn->num_files_open));
   
-  if (nwritten <= 0)
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
+       if (nwritten <= 0)
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
   
-  outsize = set_message(outbuf,1,0,True);
+       outsize = set_message(outbuf,1,0,True);
   
-  SSVAL(outbuf,smb_vwv0,nwritten);
-  return(outsize);
+       SSVAL(outbuf,smb_vwv0,nwritten);
+       return(outsize);
 }
 
 
 /****************************************************************************
   reply to a lock
 ****************************************************************************/
-int reply_lock(char *inbuf,char *outbuf)
+int reply_lock(connection_struct *conn,
+              char *inbuf,char *outbuf, int length, int dum_buffsize)
 {
-  int fnum,cnum;
-  int outsize = set_message(outbuf,0,0,True);
-  uint32 count,offset;
-  int eclass;
-  uint32 ecode;
-
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
-
-  CHECK_FNUM(fnum,cnum);
-  CHECK_ERROR(fnum);
-
-  count = IVAL(inbuf,smb_vwv1);
-  offset = IVAL(inbuf,smb_vwv3);
-
-  DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count));
+       int outsize = set_message(outbuf,0,0,True);
+       SMB_OFF_T count,offset;
+       int eclass;
+       uint32 ecode;
+       files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+
+       CHECK_FSP(fsp,conn);
+       CHECK_ERROR(fsp);
+
+       count = IVAL(inbuf,smb_vwv1);
+       offset = IVAL(inbuf,smb_vwv3);
+
+       DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
+                fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
+
+       if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
+      if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
+        /*
+         * A blocking lock was requested. Package up
+         * this smb into a queued request and push it
+         * onto the blocking lock queue.
+         */
+        if(push_blocking_lock_request(inbuf, length, -1, 0))
+          return -1;
+      }
+      return (ERROR(eclass,ecode));
+    }
 
-  if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
-    return (ERROR(eclass,ecode));
-  
-  return(outsize);
+       return(outsize);
 }
 
 
 /****************************************************************************
   reply to a unlock
 ****************************************************************************/
-int reply_unlock(char *inbuf,char *outbuf)
+int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int fnum,cnum;
   int outsize = set_message(outbuf,0,0,True);
-  uint32 count,offset;
+  SMB_OFF_T count,offset;
   int eclass;
   uint32 ecode;
-  
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
-  CHECK_FNUM(fnum,cnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_ERROR(fsp);
 
   count = IVAL(inbuf,smb_vwv1);
   offset = IVAL(inbuf,smb_vwv3);
 
-  if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
+  if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
     return (ERROR(eclass,ecode));
 
-  DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count));
+  DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
+        fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
   
   return(outsize);
 }
@@ -2464,27 +2662,24 @@ int reply_unlock(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a tdis
 ****************************************************************************/
-int reply_tdis(char *inbuf,char *outbuf)
+int reply_tdis(connection_struct *conn, 
+              char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum;
-  int outsize = set_message(outbuf,0,0,True);
-  uint16 vuid;
+       int outsize = set_message(outbuf,0,0,True);
+       uint16 vuid;
 
-  cnum = SVAL(inbuf,smb_tid);
-  vuid = SVAL(inbuf,smb_uid);
+       vuid = SVAL(inbuf,smb_uid);
 
-  if (!OPEN_CNUM(cnum)) {
-    DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
-    return(ERROR(ERRSRV,ERRinvnid));
-  }
+       if (!conn) {
+               DEBUG(4,("Invalid connection in tdis\n"));
+               return(ERROR(ERRSRV,ERRinvnid));
+       }
 
-  Connections[cnum].used = False;
+       conn->used = False;
 
-  close_cnum(cnum,vuid);
+       close_cnum(conn,vuid);
   
-  DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
-
-  return outsize;
+       return outsize;
 }
 
 
@@ -2492,266 +2687,217 @@ int reply_tdis(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a echo
 ****************************************************************************/
-int reply_echo(char *inbuf,char *outbuf)
+int reply_echo(connection_struct *conn,
+              char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum;
-  int smb_reverb = SVAL(inbuf,smb_vwv0);
-  int seq_num;
-  int data_len = smb_buflen(inbuf);
-  int outsize = set_message(outbuf,1,data_len,True);
-
-  cnum = SVAL(inbuf,smb_tid);
-
-  /* According to the latest CIFS spec we shouldn't
-     care what the TID is.
-   */
-
-#if 0
-  if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
-    {
-      DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
-      return(ERROR(ERRSRV,ERRinvnid));
-    }
-#endif
-
-  /* copy any incoming data back out */
-  if (data_len > 0)
-    memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
+       int smb_reverb = SVAL(inbuf,smb_vwv0);
+       int seq_num;
+       int data_len = smb_buflen(inbuf);
+       int outsize = set_message(outbuf,1,data_len,True);
+       
+       /* copy any incoming data back out */
+       if (data_len > 0)
+               memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
 
-  if (smb_reverb > 100)
-    {
-      DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
-      smb_reverb = 100;
-    }
+       if (smb_reverb > 100) {
+               DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
+               smb_reverb = 100;
+       }
 
-  for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
-    {
-      SSVAL(outbuf,smb_vwv0,seq_num);
+       for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
+               SSVAL(outbuf,smb_vwv0,seq_num);
 
-      smb_setlen(outbuf,outsize - 4);
+               smb_setlen(outbuf,outsize - 4);
 
-      send_smb(Client,outbuf);
-    }
+               send_smb(Client,outbuf);
+       }
 
-  DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
+       DEBUG(3,("echo %d times\n", smb_reverb));
 
-  return -1;
+       return -1;
 }
 
 
 /****************************************************************************
   reply to a printopen
 ****************************************************************************/
-int reply_printopen(char *inbuf,char *outbuf)
+int reply_printopen(connection_struct *conn, 
+                   char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  pstring fname;
-  pstring fname2;
-  int cnum;
-  int fnum = -1;
-  int outsize = 0;
-
-  *fname = *fname2 = 0;
-
-  cnum = SVAL(inbuf,smb_tid);
-
-  if (!CAN_PRINT(cnum))
-    return(ERROR(ERRDOS,ERRnoaccess));
-
-  {
-    pstring s;
-    char *p;
-    pstrcpy(s,smb_buf(inbuf)+1);
-    p = s;
-    while (*p)
-      {
-       if (!(isalnum(*p) || strchr("._-",*p)))
-         *p = 'X';
-       p++;
-      }
+       pstring fname;
+       pstring fname2;
+       int outsize = 0;
+       files_struct *fsp;
+       
+       *fname = *fname2 = 0;
+       
+       if (!CAN_PRINT(conn))
+               return(ERROR(ERRDOS,ERRnoaccess));
 
-    if (strlen(s) > 10) s[10] = 0;
+       {
+               pstring s;
+               char *p;
+               pstrcpy(s,smb_buf(inbuf)+1);
+               p = s;
+               while (*p) {
+                       if (!(isalnum((int)*p) || strchr("._-",*p)))
+                               *p = 'X';
+                       p++;
+               }
 
-    sprintf(fname,"%s.XXXXXX",s);  
-  }
+               if (strlen(s) > 10) s[10] = 0;
 
-  fnum = find_free_file();
-  if (fnum < 0)
-    return(ERROR(ERRSRV,ERRnofids));
+               slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);  
+       }
 
-  strcpy(fname2,(char *)mktemp(fname));
+       fsp = file_new();
+       if (!fsp)
+               return(ERROR(ERRSRV,ERRnofids));
+       
+       pstrcpy(fname2,(char *)mktemp(fname));
 
-  if (!check_name(fname2,cnum)) {
-         Files[fnum].reserved = False;
-         return(ERROR(ERRDOS,ERRnoaccess));
-  }
+       if (!check_name(fname2,conn)) {
+               file_free(fsp);
+               return(ERROR(ERRDOS,ERRnoaccess));
+       }
 
-  /* Open for exclusive use, write only. */
-  open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), 
-                   0, NULL, NULL);
+       /* Open for exclusive use, write only. */
+       open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
+                     (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
 
-  if (!Files[fnum].open) {
-         Files[fnum].reserved = False;
-         return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
+       if (!fsp->open) {
+               file_free(fsp);
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
 
-  /* force it to be a print file */
-  Files[fnum].print_file = True;
+       /* force it to be a print file */
+       fsp->print_file = True;
   
-  outsize = set_message(outbuf,1,0,True);
-  SSVAL(outbuf,smb_vwv0,fnum);
-  
-  DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
+       outsize = set_message(outbuf,1,0,True);
+       SSVAL(outbuf,smb_vwv0,fsp->fnum);
   
-  return(outsize);
+       DEBUG(3,("openprint %s fd=%d fnum=%d\n",
+                  fname2, fsp->fd_ptr->fd, fsp->fnum));
+
+       return(outsize);
 }
 
 
 /****************************************************************************
   reply to a printclose
 ****************************************************************************/
-int reply_printclose(char *inbuf,char *outbuf)
+int reply_printclose(connection_struct *conn,
+                    char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int fnum,cnum;
-  int outsize = set_message(outbuf,0,0,True);
-  
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
+       int outsize = set_message(outbuf,0,0,True);
+       files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
-  CHECK_FNUM(fnum,cnum);
-  CHECK_ERROR(fnum);
+       CHECK_FSP(fsp,conn);
+       CHECK_ERROR(fsp);
 
-  if (!CAN_PRINT(cnum))
-    return(ERROR(ERRDOS,ERRnoaccess));
-  
-  close_file(fnum,True);
+       if (!CAN_PRINT(conn))
+               return(ERROR(ERRDOS,ERRnoaccess));
   
-  DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
+       DEBUG(3,("printclose fd=%d fnum=%d\n",
+                fsp->fd_ptr->fd,fsp->fnum));
   
-  return(outsize);
+       close_file(fsp,True);
+
+       return(outsize);
 }
 
 
 /****************************************************************************
   reply to a printqueue
 ****************************************************************************/
-int reply_printqueue(char *inbuf,char *outbuf)
+int reply_printqueue(connection_struct *conn,
+                    char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum;
-  int outsize = set_message(outbuf,2,3,True);
-  int max_count = SVAL(inbuf,smb_vwv0);
-  int start_index = SVAL(inbuf,smb_vwv1);
-  uint16 vuid;
-
-  cnum = SVAL(inbuf,smb_tid);
-  vuid = SVAL(inbuf,smb_uid);
-
-/* allow checking the queue for anyone */
-#if 0
-  if (!CAN_PRINT(cnum))
-    return(ERROR(ERRDOS,ERRnoaccess));
-#endif
-
-  SSVAL(outbuf,smb_vwv0,0);
-  SSVAL(outbuf,smb_vwv1,0);
-  CVAL(smb_buf(outbuf),0) = 1;
-  SSVAL(smb_buf(outbuf),1,0);
+       int outsize = set_message(outbuf,2,3,True);
+       int max_count = SVAL(inbuf,smb_vwv0);
+       int start_index = SVAL(inbuf,smb_vwv1);
+
+       /* we used to allow the client to get the cnum wrong, but that
+          is really quite gross and only worked when there was only
+          one printer - I think we should now only accept it if they
+          get it right (tridge) */
+       if (!CAN_PRINT(conn))
+               return(ERROR(ERRDOS,ERRnoaccess));
+
+       SSVAL(outbuf,smb_vwv0,0);
+       SSVAL(outbuf,smb_vwv1,0);
+       CVAL(smb_buf(outbuf),0) = 1;
+       SSVAL(smb_buf(outbuf),1,0);
   
-  DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
-       timestring(),cnum,start_index,max_count));
-
-  if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
-    {
-      int i;
-      cnum = -1;
-
-      for (i=0;i<MAX_CONNECTIONS;i++)
-       if (CAN_PRINT(i) && Connections[i].printer)
-         cnum = i;
-
-      if (cnum == -1)
-       for (i=0;i<MAX_CONNECTIONS;i++)
-         if (OPEN_CNUM(i))
-           cnum = i;
-
-      if (!OPEN_CNUM(cnum))
-       return(ERROR(ERRSRV,ERRinvnid));
+       DEBUG(3,("printqueue start_index=%d max_count=%d\n",
+                start_index, max_count));
 
-      DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
-    }
-
-  if (!become_user(&Connections[cnum], cnum, vuid))
-    return(ERROR(ERRSRV,ERRinvnid));
-
-  {
-    print_queue_struct *queue = NULL;
-    char *p = smb_buf(outbuf) + 3;
-    int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
-    int num_to_get = ABS(max_count);
-    int first = (max_count>0?start_index:start_index+max_count+1);
-    int i;
-
-    if (first >= count)
-      num_to_get = 0;
-    else
-      num_to_get = MIN(num_to_get,count-first);
+       {
+               print_queue_struct *queue = NULL;
+               char *p = smb_buf(outbuf) + 3;
+               int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
+               int num_to_get = ABS(max_count);
+               int first = (max_count>0?start_index:start_index+max_count+1);
+               int i;
+
+               if (first >= count)
+                       num_to_get = 0;
+               else
+                       num_to_get = MIN(num_to_get,count-first);
     
 
-    for (i=first;i<first+num_to_get;i++)
-      {
-       put_dos_date2(p,0,queue[i].time);
-       CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
-       SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
-       SIVAL(p,7,queue[i].size);
-       CVAL(p,11) = 0;
-       StrnCpy(p+12,queue[i].user,16);
-       p += 28;
-      }
+               for (i=first;i<first+num_to_get;i++) {
+                       put_dos_date2(p,0,queue[i].time);
+                       CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
+                       SSVAL(p,5,printjob_encode(SNUM(conn), 
+                                                 queue[i].job));
+                       SIVAL(p,7,queue[i].size);
+                       CVAL(p,11) = 0;
+                       StrnCpy(p+12,queue[i].user,16);
+                       p += 28;
+               }
 
-    if (count > 0)
-      {
-       outsize = set_message(outbuf,2,28*count+3,False);         
-       SSVAL(outbuf,smb_vwv0,count);
-       SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
-       CVAL(smb_buf(outbuf),0) = 1;
-       SSVAL(smb_buf(outbuf),1,28*count);
-      }
+               if (count > 0) {
+                       outsize = set_message(outbuf,2,28*count+3,False); 
+                       SSVAL(outbuf,smb_vwv0,count);
+                       SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
+                       CVAL(smb_buf(outbuf),0) = 1;
+                       SSVAL(smb_buf(outbuf),1,28*count);
+               }
 
-    if (queue) free(queue);
+               if (queue) free(queue);
          
-    DEBUG(3,("%d entries returned in queue\n",count));
-  }
+               DEBUG(3,("%d entries returned in queue\n",count));
+       }
   
-  return(outsize);
+       return(outsize);
 }
 
 
 /****************************************************************************
   reply to a printwrite
 ****************************************************************************/
-int reply_printwrite(char *inbuf,char *outbuf)
+int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,numtowrite,fnum;
+  int numtowrite;
   int outsize = set_message(outbuf,0,0,True);
   char *data;
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
   
-  cnum = SVAL(inbuf,smb_tid);
-
-  if (!CAN_PRINT(cnum))
+  if (!CAN_PRINT(conn))
     return(ERROR(ERRDOS,ERRnoaccess));
 
-  fnum = GETFNUM(inbuf,smb_vwv0);
-
-  CHECK_FNUM(fnum,cnum);
-  CHECK_WRITE(fnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_WRITE(fsp);
+  CHECK_ERROR(fsp);
 
   numtowrite = SVAL(smb_buf(inbuf),1);
   data = smb_buf(inbuf) + 3;
   
-  if (write_file(fnum,data,numtowrite) != numtowrite)
+  if (write_file(fsp,data,numtowrite) != numtowrite)
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   
-  DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
+  DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
   
   return(outsize);
 }
@@ -2760,19 +2906,18 @@ int reply_printwrite(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a mkdir
 ****************************************************************************/
-int reply_mkdir(char *inbuf,char *outbuf)
+int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring directory;
-  int cnum;
   int outsize,ret= -1;
   BOOL bad_path = False;
  
   pstrcpy(directory,smb_buf(inbuf) + 1);
-  cnum = SVAL(inbuf,smb_tid);
-  unix_convert(directory,cnum,0,&bad_path);
+  unix_convert(directory,conn,0,&bad_path,NULL);
   
-  if (check_name(directory,cnum))
-    ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
+  if (check_name(directory, conn))
+    ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
+                             unix_mode(conn,aDIR));
   
   if (ret < 0)
   {
@@ -2783,11 +2928,11 @@ int reply_mkdir(char *inbuf,char *outbuf)
     }
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
+
   outsize = set_message(outbuf,0,0,True);
-  
-  DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
-  
+
+  DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
+
   return(outsize);
 }
 
@@ -2795,11 +2940,11 @@ int reply_mkdir(char *inbuf,char *outbuf)
 Static function used by reply_rmdir to delete an entire directory
 tree recursively.
 ****************************************************************************/
-static BOOL recursive_rmdir(char *directory)
+static BOOL recursive_rmdir(connection_struct *conn, char *directory)
 {
   char *dname = NULL;
   BOOL ret = False;
-  void *dirptr = OpenDir(-1, directory, False);
+  void *dirptr = OpenDir(conn, directory, False);
 
   if(dirptr == NULL)
     return True;
@@ -2807,7 +2952,7 @@ static BOOL recursive_rmdir(char *directory)
   while((dname = ReadDirName(dirptr)))
   {
     pstring fullname;
-    struct stat st;
+    SMB_STRUCT_STAT st;
 
     if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
       continue;
@@ -2819,11 +2964,11 @@ static BOOL recursive_rmdir(char *directory)
       ret = True;
       break;
     }
-    strcpy(fullname, directory);
-    strcat(fullname, "/");
-    strcat(fullname, dname);
+    pstrcpy(fullname, directory);
+    pstrcat(fullname, "/");
+    pstrcat(fullname, dname);
 
-    if(sys_lstat(fullname, &st) != 0)
+    if(conn->vfs_ops.lstat(fullname, &st) != 0)
     {
       ret = True;
       break;
@@ -2831,18 +2976,18 @@ static BOOL recursive_rmdir(char *directory)
 
     if(st.st_mode & S_IFDIR)
     {
-      if(recursive_rmdir(fullname)!=0)
+      if(recursive_rmdir(conn, fullname)!=0)
       {
         ret = True;
         break;
       }
-      if(sys_rmdir(fullname) != 0)
+      if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
       {
         ret = True;
         break;
       }
     }
-    else if(sys_unlink(fullname) != 0)
+    else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
     {
       ret = True;
       break;
@@ -2855,24 +3000,22 @@ static BOOL recursive_rmdir(char *directory)
 /****************************************************************************
   reply to a rmdir
 ****************************************************************************/
-int reply_rmdir(char *inbuf,char *outbuf)
+int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring directory;
-  int cnum;
   int outsize = 0;
   BOOL ok = False;
   BOOL bad_path = False;
 
-  cnum = SVAL(inbuf,smb_tid);
   pstrcpy(directory,smb_buf(inbuf) + 1);
-  unix_convert(directory,cnum,0,&bad_path);
+  unix_convert(directory,conn, NULL,&bad_path,NULL);
   
-  if (check_name(directory,cnum))
+  if (check_name(directory,conn))
     {
 
       dptr_closepath(directory,SVAL(inbuf,smb_pid));
-      ok = (sys_rmdir(directory) == 0);
-      if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
+      ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0);
+      if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
         {
           /* Check to see if the only thing in this directory are
              vetoed files/directories. If so then delete them and
@@ -2880,7 +3023,7 @@ int reply_rmdir(char *inbuf,char *outbuf)
              do a recursive delete) then fail the rmdir. */
           BOOL all_veto_files = True;
           char *dname;
-          void *dirptr = OpenDir(cnum, directory, False);
+          void *dirptr = OpenDir(conn, directory, False);
 
           if(dirptr != NULL)
             {
@@ -2889,7 +3032,7 @@ int reply_rmdir(char *inbuf,char *outbuf)
                    {
                   if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
                     continue;
-                  if(!IS_VETO_PATH(cnum, dname))
+                  if(!IS_VETO_PATH(conn, dname))
                     {
                       all_veto_files = False;
                       break;
@@ -2901,7 +3044,7 @@ int reply_rmdir(char *inbuf,char *outbuf)
                   while ((dname = ReadDirName(dirptr)))
                     {
                       pstring fullname;
-                      struct stat st;
+                      SMB_STRUCT_STAT st;
 
                       if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
                         continue;
@@ -2913,27 +3056,28 @@ int reply_rmdir(char *inbuf,char *outbuf)
                           break;
                         }
                       pstrcpy(fullname, directory);
-                      strcat(fullname, "/");
-                      strcat(fullname, dname);
+                      pstrcat(fullname, "/");
+                      pstrcat(fullname, dname);
                       
-                      if(sys_lstat(fullname, &st) != 0)
+                      if(conn->vfs_ops.lstat(fullname, &st) != 0)
                         break;
                       if(st.st_mode & S_IFDIR)
                       {
-                        if(lp_recursive_veto_delete(SNUM(cnum)))
+                        if(lp_recursive_veto_delete(SNUM(conn)))
                         {
-                          if(recursive_rmdir(fullname) != 0)
+                         DEBUG(0, ("ERROR: recursive_rmdir()\n"));
+                          if(recursive_rmdir(conn, fullname) != 0)
                             break;
                         }
-                        if(sys_rmdir(fullname) != 0)
+                        if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
                           break;
                       }
-                      else if(sys_unlink(fullname) != 0)
+                      else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
                         break;
                     }
                   CloseDir(dirptr);
                   /* Retry the rmdir */
-                  ok = (sys_rmdir(directory) == 0);
+                  ok = (conn->vfs_ops.rmdir(dos_to_unix(directory,False)) == 0);
                 }
               else
                 CloseDir(dirptr);
@@ -2959,7 +3103,7 @@ int reply_rmdir(char *inbuf,char *outbuf)
  
   outsize = set_message(outbuf,0,0,True);
   
-  DEBUG(3,("%s rmdir %s\n",timestring(),directory));
+  DEBUG( 3, ( "rmdir %s\n", directory ) );
   
   return(outsize);
 }
@@ -3020,10 +3164,10 @@ static BOOL resolve_wildcards(char *name1,char *name2)
     if (*p) p++;
   }
 
-  strcpy(name2,root2);
+  pstrcpy(name2,root2);
   if (ext2[0]) {
-    strcat(name2,".");
-    strcat(name2,ext2);
+    pstrcat(name2,".");
+    pstrcat(name2,ext2);
   }
 
   return(True);
@@ -3032,202 +3176,236 @@ static BOOL resolve_wildcards(char *name1,char *name2)
 /*******************************************************************
 check if a user is allowed to rename a file
 ********************************************************************/
-static BOOL can_rename(char *fname,int cnum)
+static BOOL can_rename(char *fname,connection_struct *conn)
 {
-  struct stat sbuf;
+  SMB_STRUCT_STAT sbuf;
 
-  if (!CAN_WRITE(cnum)) return(False);
+  if (!CAN_WRITE(conn)) return(False);
 
-  if (sys_lstat(fname,&sbuf) != 0) return(False);
-  if (!check_file_sharing(cnum,fname,True)) return(False);
+  if (conn->vfs_ops.lstat(fname,&sbuf) != 0) return(False);
+  if (!check_file_sharing(conn,fname,True)) return(False);
 
   return(True);
 }
 
 /****************************************************************************
-  reply to a mv
+ The guts of the rename command, split out so it may be called by the NT SMB
+ code. 
 ****************************************************************************/
-int reply_mv(char *inbuf,char *outbuf)
+int rename_internals(connection_struct *conn, 
+                    char *inbuf, char *outbuf, char *name, 
+                    char *newname, BOOL replace_if_exists)
 {
-  int outsize = 0;
-  pstring name;
-  int cnum;
-  pstring directory;
-  pstring mask,newname;
-  pstring newname_last_component;
-  char *p;
-  int count=0;
-  int error = ERRnoaccess;
-  BOOL has_wild;
-  BOOL exists=False;
-  BOOL bad_path1 = False;
-  BOOL bad_path2 = False;
-
-  *directory = *mask = 0;
-
-  cnum = SVAL(inbuf,smb_tid);
-  
-  pstrcpy(name,smb_buf(inbuf) + 1);
-  pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
-   
-  DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
-   
-  unix_convert(name,cnum,0,&bad_path1);
-  unix_convert(newname,cnum,newname_last_component,&bad_path2);
-
-  /*
-   * Split the old name into directory and last component
-   * strings. Note that unix_convert may have stripped off a 
-   * leading ./ from both name and newname if the rename is 
-   * at the root of the share. We need to make sure either both
-   * name and newname contain a / character or neither of them do
-   * as this is checked in resolve_wildcards().
-   */
-
-  p = strrchr(name,'/');
-  if (!p) {
-    strcpy(directory,".");
-    strcpy(mask,name);
-  } else {
-    *p = 0;
-    strcpy(directory,name);
-    strcpy(mask,p+1);
-    *p = '/'; /* Replace needed for exceptional test below. */
-  }
-
-  if (is_mangled(mask))
-    check_mangled_stack(mask);
-
-  has_wild = strchr(mask,'*') || strchr(mask,'?');
-
-  if (!has_wild) {
-    BOOL is_short_name = is_8_3(name, True);
-
-    /* Add a terminating '/' to the directory name. */
-    strcat(directory,"/");
-    strcat(directory,mask);
-
-    /* Ensure newname contains a '/' also */
-    if(strrchr(newname,'/') == 0) {
-      pstring tmpstr;
-
-      strcpy(tmpstr, "./");
-      strcat(tmpstr, newname);
-      strcpy(newname, tmpstr);
-    }
-  
-    DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", 
-            case_sensitive, case_preserve, short_case_preserve, directory, 
-            newname, newname_last_component, is_short_name));
-
-    /*
-     * Check for special case with case preserving and not
-     * case sensitive, if directory and newname are identical,
-     * and the old last component differs from the original
-     * last component only by case, then we should allow
-     * the rename (user is trying to change the case of the
-     * filename).
-     */
-    if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) || 
-            ((short_case_preserve == True) && (is_short_name == True))) &&
-       strcsequal(directory, newname)) {
-      pstring newname_modified_last_component;
-
-      /*
-       * Get the last component of the modified name.
-       * Note that we guarantee that newname contains a '/'
-       * character above.
-       */
-      p = strrchr(newname,'/');
-      strcpy(newname_modified_last_component,p+1);
+       pstring directory;
+       pstring mask;
+       pstring newname_last_component;
+       char *p;
+       BOOL has_wild;
+       BOOL bad_path1 = False;
+       BOOL bad_path2 = False;
+       int count=0;
+       int error = ERRnoaccess;
+       BOOL exists=False;
+
+       *directory = *mask = 0;
+
+       unix_convert(name,conn,0,&bad_path1,NULL);
+       unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
 
-      if(strcsequal(newname_modified_last_component, 
-                   newname_last_component) == False) {
        /*
-        * Replace the modified last component with
-        * the original.
+        * Split the old name into directory and last component
+        * strings. Note that unix_convert may have stripped off a 
+        * leading ./ from both name and newname if the rename is 
+        * at the root of the share. We need to make sure either both
+        * name and newname contain a / character or neither of them do
+        * as this is checked in resolve_wildcards().
         */
-        strcpy(p+1, newname_last_component);
-      }
-    }
+       
+       p = strrchr(name,'/');
+       if (!p) {
+               pstrcpy(directory,".");
+               pstrcpy(mask,name);
+       } else {
+               *p = 0;
+               pstrcpy(directory,name);
+               pstrcpy(mask,p+1);
+               *p = '/'; /* Replace needed for exceptional test below. */
+       }
 
-    if (resolve_wildcards(directory,newname) && 
-       can_rename(directory,cnum) && 
-       !file_exist(newname,NULL) &&
-       !sys_rename(directory,newname)) count++;
+       if (is_mangled(mask))
+               check_mangled_cache( mask );
 
-    DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
-                         directory,newname));
+       has_wild = strchr(mask,'*') || strchr(mask,'?');
 
-    if (!count) exists = file_exist(directory,NULL);
-    if (!count && exists && file_exist(newname,NULL)) {
-      exists = True;
-      error = 183;
-    }
-  } else {
-    void *dirptr = NULL;
-    char *dname;
-    pstring destname;
-
-    if (check_name(directory,cnum))
-      dirptr = OpenDir(cnum, directory, True);
+       if (!has_wild) {
+               /*
+                * No wildcards - just process the one file.
+                */
+               BOOL is_short_name = is_8_3(name, True);
 
-    if (dirptr)
-      {
-       error = ERRbadfile;
+               /* Add a terminating '/' to the directory name. */
+               pstrcat(directory,"/");
+               pstrcat(directory,mask);
+               
+               /* Ensure newname contains a '/' also */
+               if(strrchr(newname,'/') == 0) {
+                       pstring tmpstr;
+                       
+                       pstrcpy(tmpstr, "./");
+                       pstrcat(tmpstr, newname);
+                       pstrcpy(newname, tmpstr);
+               }
+               
+               DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", 
+                        case_sensitive, case_preserve, short_case_preserve, directory, 
+                        newname, newname_last_component, is_short_name));
+
+               /*
+                * Check for special case with case preserving and not
+                * case sensitive, if directory and newname are identical,
+                * and the old last component differs from the original
+                * last component only by case, then we should allow
+                * the rename (user is trying to change the case of the
+                * filename).
+                */
+               if((case_sensitive == False) && 
+                  (((case_preserve == True) && 
+                    (is_short_name == False)) || 
+                   ((short_case_preserve == True) && 
+                    (is_short_name == True))) &&
+                  strcsequal(directory, newname)) {
+                       pstring newname_modified_last_component;
+
+                       /*
+                        * Get the last component of the modified name.
+                        * Note that we guarantee that newname contains a '/'
+                        * character above.
+                        */
+                       p = strrchr(newname,'/');
+                       pstrcpy(newname_modified_last_component,p+1);
+                       
+                       if(strcsequal(newname_modified_last_component, 
+                                     newname_last_component) == False) {
+                               /*
+                                * Replace the modified last component with
+                                * the original.
+                                */
+                               pstrcpy(p+1, newname_last_component);
+                       }
+               }
+               
+               if(replace_if_exists) {
+                       /*
+                        * NT SMB specific flag - rename can overwrite
+                        * file with the same name so don't check for
+                        * dos_file_exist().
+                        */
+                       if(resolve_wildcards(directory,newname) &&
+                          can_rename(directory,conn) &&
+                          !conn->vfs_ops.rename(dos_to_unix(directory,False),
+                                                newname))
+                               count++;
+               } else {
+                       if (resolve_wildcards(directory,newname) && 
+                           can_rename(directory,conn) && 
+                           !vfs_file_exist(conn,dos_to_unix(newname,False),NULL) &&
+                           !conn->vfs_ops.rename(dos_to_unix(directory,False),
+                                                 newname))
+                               count++;
+               }
 
-       if (strequal(mask,"????????.???"))
-         strcpy(mask,"*");
+               DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
+                         directory,newname));
+               
+               if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
+               if (!count && exists && vfs_file_exist(conn,dos_to_unix(newname,False),NULL)) {
+                       exists = True;
+                       error = ERRrename;
+               }
+       } else {
+               /*
+                * Wildcards - process each file that matches.
+                */
+               void *dirptr = NULL;
+               char *dname;
+               pstring destname;
+               
+               if (check_name(directory,conn))
+                       dirptr = OpenDir(conn, directory, True);
+               
+               if (dirptr) {
+                       error = ERRbadfile;
+                       
+                       if (strequal(mask,"????????.???"))
+                               pstrcpy(mask,"*");
+                       
+                       while ((dname = ReadDirName(dirptr))) {
+                               pstring fname;
+                               pstrcpy(fname,dname);
+                               
+                               if(!mask_match(fname, mask, case_sensitive, False))
+                                       continue;
+                               
+                               error = ERRnoaccess;
+                               slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
+                               if (!can_rename(fname,conn)) {
+                                       DEBUG(6,("rename %s refused\n", fname));
+                                       continue;
+                               }
+                               pstrcpy(destname,newname);
+                               
+                               if (!resolve_wildcards(fname,destname)) {
+                                       DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
+                                       continue;
+                               }
+                               
+                               if (!replace_if_exists && vfs_file_exist(conn,dos_to_unix(destname,False),NULL)) {
+                                       DEBUG(6,("file_exist %s\n", destname));
+                                       error = 183;
+                                       continue;
+                               }
+                               
+                               if (!conn->vfs_ops.rename(dos_to_unix(fname,False),destname))
+                                       count++;
+                               DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
+                       }
+                       CloseDir(dirptr);
+               }
+       }
+       
+       if (count == 0) {
+               if (exists)
+                       return(ERROR(ERRDOS,error));
+               else {
+                       if((errno == ENOENT) && (bad_path1 || bad_path2)) {
+                               unix_ERR_class = ERRDOS;
+                               unix_ERR_code = ERRbadpath;
+                       }
+                       return(UNIXERROR(ERRDOS,error));
+               }
+       }
+       
+       return 0;
+}
 
-       while ((dname = ReadDirName(dirptr)))
-         {
-           pstring fname;
-           pstrcpy(fname,dname);
-           
-           if(!mask_match(fname, mask, case_sensitive, False)) continue;
+/****************************************************************************
+ Reply to a mv.
+****************************************************************************/
 
-           error = ERRnoaccess;
-           sprintf(fname,"%s/%s",directory,dname);
-           if (!can_rename(fname,cnum)) {
-                   DEBUG(6,("rename %s refused\n", fname));
-                   continue;
-           }
-           pstrcpy(destname,newname);
+int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+{
+  int outsize = 0;
+  pstring name;
+  pstring newname;
 
-           if (!resolve_wildcards(fname,destname)) {
-                   DEBUG(6,("resolve_wildcards %s %s failed\n", 
-                            fname, destname));
-                   continue;
-           }
+  pstrcpy(name,smb_buf(inbuf) + 1);
+  pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
+   
+  DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
 
-           if (file_exist(destname,NULL)) {
-                   DEBUG(6,("file_exist %s\n", 
-                            destname));
-                   error = 183;
-                   continue;
-           }
-           if (!sys_rename(fname,destname)) count++;
-           DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
-         }
-       CloseDir(dirptr);
-      }
-  }
-  
-  if (count == 0) {
-    if (exists)
-      return(ERROR(ERRDOS,error));
-    else
-    {
-      if((errno == ENOENT) && (bad_path1 || bad_path2))
-      {
-        unix_ERR_class = ERRDOS;
-        unix_ERR_code = ERRbadpath;
-      }
-      return(UNIXERROR(ERRDOS,error));
-    }
-  }
-  
-  outsize = set_message(outbuf,0,0,True);
+  outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
+  if(outsize == 0) 
+    outsize = set_message(outbuf,0,0,True);
   
   return(outsize);
 }
@@ -3235,13 +3413,14 @@ int reply_mv(char *inbuf,char *outbuf)
 /*******************************************************************
   copy a file as part of a reply_copy
   ******************************************************************/
-static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
+
+static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
                      int count,BOOL target_is_directory)
 {
   int Access,action;
-  struct stat st;
-  int ret=0;
-  int fnum1,fnum2;
+  SMB_STRUCT_STAT st;
+  int ret=-1;
+  files_struct *fsp1,*fsp2;
   pstring dest;
   
   pstrcpy(dest,dest1);
@@ -3251,48 +3430,61 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
       p++;
     else
       p = src;
-    strcat(dest,"/");
-    strcat(dest,p);
+    pstrcat(dest,"/");
+    pstrcat(dest,p);
   }
 
-  if (!file_exist(src,&st)) return(False);
+  if (!vfs_file_exist(conn,dos_to_unix(src,False),&st))
+    return(False);
+
+  fsp1 = file_new();
+  if (!fsp1) 
+    return(False);
 
-  fnum1 = find_free_file();
-  if (fnum1<0) return(False);
-  open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
-                  1,0,0,&Access,&action);
+  open_file_shared(fsp1, conn, src,
+      SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_RDONLY),
+      (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN), 0, 0, &Access, &action);
 
-  if (!Files[fnum1].open) {
-         Files[fnum1].reserved = False;
+  if (!fsp1->open) {
+         file_free(fsp1);
          return(False);
   }
 
   if (!target_is_directory && count)
     ofun = 1;
 
-  fnum2 = find_free_file();
-  if (fnum2<0) {
-    close_file(fnum1,False);
-    return(False);
+  fsp2 = file_new();
+  if (!fsp2) {
+         close_file(fsp1,False);
+         return(False);
   }
-  open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
-                  ofun,st.st_mode,0,&Access,&action);
+  open_file_shared(fsp2, conn, dest,
+      SET_DENY_MODE(DENY_NONE) | SET_OPEN_MODE(DOS_OPEN_WRONLY),
+      ofun, st.st_mode, 0, &Access, &action);
 
-  if (!Files[fnum2].open) {
-    close_file(fnum1,False);
-    Files[fnum2].reserved = False;
+  if (!fsp2->open) {
+    close_file(fsp1,False);
+    file_free(fsp2);
     return(False);
   }
 
   if ((ofun&3) == 1) {
-    lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
+    if(conn->vfs_ops.lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
+      DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
+               strerror(errno) ));
+      /*
+       * Stop the copy from occurring.
+       */
+      ret = -1;
+      st.st_size = 0;
+    }
   }
   
   if (st.st_size)
-    ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
+    ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0);
 
-  close_file(fnum1,False);
-  close_file(fnum2,False);
+  close_file(fsp1,False);
+  close_file(fsp2,False);
 
   return(ret == st.st_size);
 }
@@ -3302,11 +3494,10 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
 /****************************************************************************
   reply to a file copy.
   ****************************************************************************/
-int reply_copy(char *inbuf,char *outbuf)
+int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int outsize = 0;
   pstring name;
-  int cnum;
   pstring directory;
   pstring mask,newname;
   char *p;
@@ -3323,23 +3514,21 @@ int reply_copy(char *inbuf,char *outbuf)
 
   *directory = *mask = 0;
 
-  cnum = SVAL(inbuf,smb_tid);
-  
   pstrcpy(name,smb_buf(inbuf));
   pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
    
   DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
    
-  if (tid2 != cnum) {
+  if (tid2 != conn->cnum) {
     /* can't currently handle inter share copies XXXX */
     DEBUG(3,("Rejecting inter-share copy\n"));
     return(ERROR(ERRSRV,ERRinvdevice));
   }
 
-  unix_convert(name,cnum,0,&bad_path1);
-  unix_convert(newname,cnum,0,&bad_path2);
+  unix_convert(name,conn,0,&bad_path1,NULL);
+  unix_convert(newname,conn,0,&bad_path2,NULL);
 
-  target_is_directory = directory_exist(newname,NULL);
+  target_is_directory = dos_directory_exist(newname,NULL);
 
   if ((flags&1) && target_is_directory) {
     return(ERROR(ERRDOS,ERRbadfile));
@@ -3349,7 +3538,7 @@ int reply_copy(char *inbuf,char *outbuf)
     return(ERROR(ERRDOS,ERRbadpath));
   }
 
-  if ((flags&(1<<5)) && directory_exist(name,NULL)) {
+  if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
     /* wants a tree copy! XXXX */
     DEBUG(3,("Rejecting tree copy\n"));
     return(ERROR(ERRSRV,ERRerror));    
@@ -3357,40 +3546,40 @@ int reply_copy(char *inbuf,char *outbuf)
 
   p = strrchr(name,'/');
   if (!p) {
-    strcpy(directory,"./");
-    strcpy(mask,name);
+    pstrcpy(directory,"./");
+    pstrcpy(mask,name);
   } else {
     *p = 0;
-    strcpy(directory,name);
-    strcpy(mask,p+1);
+    pstrcpy(directory,name);
+    pstrcpy(mask,p+1);
   }
 
   if (is_mangled(mask))
-    check_mangled_stack(mask);
+    check_mangled_cache( mask );
 
   has_wild = strchr(mask,'*') || strchr(mask,'?');
 
   if (!has_wild) {
-    strcat(directory,"/");
-    strcat(directory,mask);
+    pstrcat(directory,"/");
+    pstrcat(directory,mask);
     if (resolve_wildcards(directory,newname) && 
-       copy_file(directory,newname,cnum,ofun,
+       copy_file(directory,newname,conn,ofun,
                  count,target_is_directory)) count++;
-    if (!count) exists = file_exist(directory,NULL);
+    if (!count) exists = vfs_file_exist(conn,dos_to_unix(directory,False),NULL);
   } else {
     void *dirptr = NULL;
     char *dname;
     pstring destname;
 
-    if (check_name(directory,cnum))
-      dirptr = OpenDir(cnum, directory, True);
+    if (check_name(directory,conn))
+      dirptr = OpenDir(conn, directory, True);
 
     if (dirptr)
       {
        error = ERRbadfile;
 
        if (strequal(mask,"????????.???"))
-         strcpy(mask,"*");
+         pstrcpy(mask,"*");
 
        while ((dname = ReadDirName(dirptr)))
          {
@@ -3400,10 +3589,10 @@ int reply_copy(char *inbuf,char *outbuf)
            if(!mask_match(fname, mask, case_sensitive, False)) continue;
 
            error = ERRnoaccess;
-           sprintf(fname,"%s/%s",directory,dname);
-           strcpy(destname,newname);
+           slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+           pstrcpy(destname,newname);
            if (resolve_wildcards(fname,destname) && 
-               copy_file(directory,newname,cnum,ofun,
+               copy_file(directory,newname,conn,ofun,
                          count,target_is_directory)) count++;
            DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
          }
@@ -3431,72 +3620,64 @@ int reply_copy(char *inbuf,char *outbuf)
   return(outsize);
 }
 
-
-
 /****************************************************************************
   reply to a setdir
 ****************************************************************************/
-int reply_setdir(char *inbuf,char *outbuf)
+int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,snum;
+  int snum;
   int outsize = 0;
   BOOL ok = False;
   pstring newdir;
   
-  cnum = SVAL(inbuf,smb_tid);
-  
-  snum = Connections[cnum].service;
+  snum = SNUM(conn);
   if (!CAN_SETDIR(snum))
     return(ERROR(ERRDOS,ERRnoaccess));
   
   pstrcpy(newdir,smb_buf(inbuf) + 1);
   strlower(newdir);
   
-  if (strlen(newdir) == 0)
-    ok = True;
-  else
-    {
-      ok = directory_exist(newdir,NULL);
-      if (ok)
-       string_set(&Connections[cnum].connectpath,newdir);
-    }
+  if (strlen(newdir) == 0) {
+         ok = True;
+  } else {
+         ok = dos_directory_exist(newdir,NULL);
+         if (ok) {
+                 string_set(&conn->connectpath,newdir);
+         }
+  }
   
   if (!ok)
-    return(ERROR(ERRDOS,ERRbadpath));
+         return(ERROR(ERRDOS,ERRbadpath));
   
   outsize = set_message(outbuf,0,0,True);
   CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
   
-  DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
-  
+  DEBUG(3,("setdir %s\n", newdir));
+
   return(outsize);
 }
 
-
 /****************************************************************************
   reply to a lockingX request
 ****************************************************************************/
-int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
+int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
-  int fnum = GETFNUM(inbuf,smb_vwv2);
+  files_struct *fsp = file_fsp(inbuf,smb_vwv2);
   unsigned char locktype = CVAL(inbuf,smb_vwv3);
 #if 0
   unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
 #endif
   uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
   uint16 num_locks = SVAL(inbuf,smb_vwv7);
-  uint32 count, offset;
-
-  int cnum;
+  SMB_OFF_T count = 0, offset = 0;
+  int32 lock_timeout = IVAL(inbuf,smb_vwv4);
   int i;
   char *data;
   uint32 ecode=0, dummy2;
   int eclass=0, dummy1;
-
-  cnum = SVAL(inbuf,smb_tid);
-
-  CHECK_FNUM(fnum,cnum);
-  CHECK_ERROR(fnum);
+  BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
+  CHECK_FSP(fsp,conn);
+  CHECK_ERROR(fsp);
 
   data = smb_buf(inbuf);
 
@@ -3506,31 +3687,31 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
   if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
   {
     int token;
-    files_struct *fsp = &Files[fnum];
-    uint32 dev = fsp->fd_ptr->dev;
-    uint32 inode = fsp->fd_ptr->inode;
+    SMB_DEV_T dev = fsp->fd_ptr->dev;
+    SMB_INO_T inode = fsp->fd_ptr->inode;
 
     DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
-              fnum));
+              fsp->fnum));
     /*
      * Make sure we have granted an oplock on this file.
      */
     if(!fsp->granted_oplock)
     {
       DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
-no oplock granted on this file.\n", fnum));
+no oplock granted on this file.\n", fsp->fnum));
       return ERROR(ERRDOS,ERRlock);
     }
 
     /* Remove the oplock flag from the sharemode. */
-    lock_share_entry(fsp->cnum, dev, inode, &token);
-    if(remove_share_oplock( fnum, token)==False) {
+    lock_share_entry(fsp->conn, dev, inode, &token);
+    if(remove_share_oplock(token, fsp)==False) {
+
            DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
-dev = %x, inode = %x\n", 
-                    fnum, dev, inode));
-           unlock_share_entry(fsp->cnum, dev, inode, token);
+dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
+
+           unlock_share_entry(fsp->conn, dev, inode, token);
     } else {
-           unlock_share_entry(fsp->cnum, dev, inode, token);
+           unlock_share_entry(fsp->conn, dev, inode, token);
 
            /* Clear the granted flag and return. */
            fsp->granted_oplock = False;
@@ -3551,40 +3732,93 @@ dev = %x, inode = %x\n",
   /* Data now points at the beginning of the list
      of smb_unlkrng structs */
   for(i = 0; i < (int)num_ulocks; i++) {
-    count = IVAL(data,SMB_LKLEN_OFFSET(i));
-    offset = IVAL(data,SMB_LKOFF_OFFSET(i));
-    if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
+    if(!large_file_format) {
+      count = IVAL(data,SMB_LKLEN_OFFSET(i));
+      offset = IVAL(data,SMB_LKOFF_OFFSET(i));
+    }
+#ifdef LARGE_SMB_OFF_T
+    else {
+      count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
+              ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
+      offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
+               ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
+    }
+#endif /* LARGE_SMB_OFF_T */
+
+    DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
+          (double)offset, (double)count, fsp->fsp_name ));
+
+    if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
       return ERROR(eclass,ecode);
   }
 
+  /* Setup the timeout in seconds. */
+  lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
+
   /* Now do any requested locks */
-  data += 10*num_ulocks;
+  data += ((large_file_format ? 20 : 10)*num_ulocks);
+
   /* Data now points at the beginning of the list
      of smb_lkrng structs */
+
   for(i = 0; i < (int)num_locks; i++) {
-    count = IVAL(data,SMB_LKLEN_OFFSET(i)); 
-    offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
-    if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
+    if(!large_file_format) {
+      count = IVAL(data,SMB_LKLEN_OFFSET(i)); 
+      offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
+    }
+#ifdef LARGE_SMB_OFF_T
+    else {
+      count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
+              ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
+      offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
+               ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
+    }
+#endif /* LARGE_SMB_OFF_T */
+    DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
+          (double)offset, (double)count, fsp->fsp_name ));
+
+    if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
+                &eclass, &ecode)) {
+      if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
+        /*
+         * A blocking lock was requested. Package up
+         * this smb into a queued request and push it
+         * onto the blocking lock queue.
+         */
+        if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
+          return -1;
+      }
       break;
+    }
   }
 
   /* If any of the above locks failed, then we must unlock
      all of the previous locks (X/Open spec). */
   if(i != num_locks && num_locks != 0) {
     for(; i >= 0; i--) {
-      count = IVAL(data,SMB_LKLEN_OFFSET(i));  
-      offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
-      do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
+      if(!large_file_format) {
+        count = IVAL(data,SMB_LKLEN_OFFSET(i));  
+        offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
+      }
+#ifdef LARGE_SMB_OFF_T
+      else {
+        count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
+                ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
+        offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
+                 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
+      }
+#endif /* LARGE_SMB_OFF_T */
+
+      do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
     }
     return ERROR(eclass,ecode);
   }
 
   set_message(outbuf,2,0,True);
   
-  DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
-       timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
-
-  chain_fnum = fnum;
+  DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
+       fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
 
   return chain_reply(inbuf,outbuf,length,bufsize);
 }
@@ -3593,17 +3827,18 @@ dev = %x, inode = %x\n",
 /****************************************************************************
   reply to a SMBreadbmpx (read block multiplex) request
 ****************************************************************************/
-int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
+int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
-  int cnum,fnum;
-  int nread = -1;
-  int total_read;
+  ssize_t nread = -1;
+  ssize_t total_read;
   char *data;
-  uint32 startpos;
-  int outsize, mincount, maxcount;
+  SMB_OFF_T startpos;
+  int outsize;
+  size_t maxcount;
   int max_per_packet;
-  int tcount;
+  size_t tcount;
   int pad;
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
   /* this function doesn't seem to work - disable by default */
   if (!lp_readbmpx())
@@ -3611,16 +3846,12 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
 
   outsize = set_message(outbuf,8,0,True);
 
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
-
-  CHECK_FNUM(fnum,cnum);
-  CHECK_READ(fnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_READ(fsp);
+  CHECK_ERROR(fsp);
 
   startpos = IVAL(inbuf,smb_vwv1);
   maxcount = SVAL(inbuf,smb_vwv3);
-  mincount = SVAL(inbuf,smb_vwv4);
 
   data = smb_buf(outbuf);
   pad = ((long)data)%4;
@@ -3631,19 +3862,19 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
   tcount = maxcount;
   total_read = 0;
 
-  if (is_locked(fnum,cnum,maxcount,startpos))
+  if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
     return(ERROR(ERRDOS,ERRlock));
        
   do
     {
-      int N = MIN(max_per_packet,tcount-total_read);
+      size_t N = MIN(max_per_packet,tcount-total_read);
   
-      nread = read_file(fnum,data,startpos,N);
+      nread = read_file(fsp,data,startpos,N);
 
       if (nread <= 0) nread = 0;
 
-      if (nread < N)
-       tcount = total_read + nread;
+      if (nread < (ssize_t)N)
+        tcount = total_read + nread;
 
       set_message(outbuf,8,nread,False);
       SIVAL(outbuf,smb_vwv0,startpos);
@@ -3656,30 +3887,29 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
       total_read += nread;
       startpos += nread;
     }
-  while (total_read < tcount);
+  while (total_read < (ssize_t)tcount);
 
   return(-1);
 }
 
-
 /****************************************************************************
   reply to a SMBwritebmpx (write block multiplex primary) request
 ****************************************************************************/
-int reply_writebmpx(char *inbuf,char *outbuf)
+int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,numtowrite,fnum;
-  int nwritten = -1;
+  size_t numtowrite;
+  ssize_t nwritten = -1;
   int outsize = 0;
-  uint32 startpos;
-  int tcount, write_through, smb_doff;
+  SMB_OFF_T startpos;
+  size_t tcount;
+  BOOL write_through;
+  int smb_doff;
   char *data;
-  
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
-  CHECK_FNUM(fnum,cnum);
-  CHECK_WRITE(fnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_WRITE(fsp);
+  CHECK_ERROR(fsp);
 
   tcount = SVAL(inbuf,smb_vwv1);
   startpos = IVAL(inbuf,smb_vwv3);
@@ -3693,41 +3923,43 @@ int reply_writebmpx(char *inbuf,char *outbuf)
      not an SMBwritebmpx - set this up now so we don't forget */
   CVAL(outbuf,smb_com) = SMBwritec;
 
-  if (is_locked(fnum,cnum,tcount,startpos))
+  if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
     return(ERROR(ERRDOS,ERRlock));
 
-  seek_file(fnum,startpos);
-  nwritten = write_file(fnum,data,numtowrite);
+  if(seek_file(fsp,startpos) == -1)
+    return(UNIXERROR(ERRDOS,ERRnoaccess));
+
+  nwritten = write_file(fsp,data,numtowrite);
 
-  if(lp_syncalways(SNUM(cnum)) || write_through)
-    sync_file(fnum);
+  if(lp_syncalways(SNUM(conn)) || write_through)
+    conn->vfs_ops.sync(conn, fsp);
   
-  if(nwritten < numtowrite)
+  if(nwritten < (ssize_t)numtowrite)
     return(UNIXERROR(ERRHRD,ERRdiskfull));
 
   /* If the maximum to be written to this file
      is greater than what we just wrote then set
      up a secondary struct to be attached to this
      fd, we will use this to cache error messages etc. */
-  if(tcount > nwritten) 
+  if((ssize_t)tcount > nwritten) 
+  {
+    write_bmpx_struct *wbms;
+    if(fsp->wbmpx_ptr != NULL)
+      wbms = fsp->wbmpx_ptr; /* Use an existing struct */
+    else
+      wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
+    if(!wbms)
     {
-      write_bmpx_struct *wbms;
-      if(Files[fnum].wbmpx_ptr != NULL)
-       wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
-      else
-       wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
-      if(!wbms)
-       {
-         DEBUG(0,("Out of memory in reply_readmpx\n"));
-         return(ERROR(ERRSRV,ERRnoresource));
-       }
-      wbms->wr_mode = write_through;
-      wbms->wr_discard = False; /* No errors yet */
-      wbms->wr_total_written = nwritten;
-      wbms->wr_errclass = 0;
-      wbms->wr_error = 0;
-      Files[fnum].wbmpx_ptr = wbms;
+      DEBUG(0,("Out of memory in reply_readmpx\n"));
+      return(ERROR(ERRSRV,ERRnoresource));
     }
+    wbms->wr_mode = write_through;
+    wbms->wr_discard = False; /* No errors yet */
+    wbms->wr_total_written = nwritten;
+    wbms->wr_errclass = 0;
+    wbms->wr_error = 0;
+    fsp->wbmpx_ptr = wbms;
+  }
 
   /* We are returning successfully, set the message type back to
      SMBwritebmpx */
@@ -3737,9 +3969,9 @@ int reply_writebmpx(char *inbuf,char *outbuf)
   
   SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
   
-  DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
-       timestring(),fnum,cnum,numtowrite,nwritten));
-  
+  DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
+           fsp->fnum, numtowrite, nwritten ) );
+
   if (write_through && tcount==nwritten) {
     /* we need to send both a primary and a secondary response */
     smb_setlen(outbuf,outsize - 4);
@@ -3758,21 +3990,22 @@ int reply_writebmpx(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a SMBwritebs (write block multiplex secondary) request
 ****************************************************************************/
-int reply_writebs(char *inbuf,char *outbuf)
+int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,numtowrite,fnum;
-  int nwritten = -1;
+  size_t numtowrite;
+  ssize_t nwritten = -1;
   int outsize = 0;
-  int32 startpos;
-  int tcount, write_through, smb_doff;
+  SMB_OFF_T startpos;
+  size_t tcount;
+  BOOL write_through;
+  int smb_doff;
   char *data;
   write_bmpx_struct *wbms;
-  BOOL send_response = False;
-  
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
-  CHECK_FNUM(fnum,cnum);
-  CHECK_WRITE(fnum);
+  BOOL send_response = False; 
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+
+  CHECK_FSP(fsp,conn);
+  CHECK_WRITE(fsp);
 
   tcount = SVAL(inbuf,smb_vwv1);
   startpos = IVAL(inbuf,smb_vwv2);
@@ -3786,7 +4019,7 @@ int reply_writebs(char *inbuf,char *outbuf)
 
   /* This fd should have an auxiliary struct attached,
      check that it does */
-  wbms = Files[fnum].wbmpx_ptr;
+  wbms = fsp->wbmpx_ptr;
   if(!wbms) return(-1);
 
   /* If write through is set we can return errors, else we must
@@ -3797,38 +4030,51 @@ int reply_writebs(char *inbuf,char *outbuf)
   if(wbms->wr_discard)
     return -1; /* Just discard the packet */
 
-  seek_file(fnum,startpos);
-  nwritten = write_file(fnum,data,numtowrite);
+  if(seek_file(fsp,startpos) == -1)
+  {
+    if(write_through)
+    {
+      /* We are returning an error - we can delete the aux struct */
+      if (wbms) free((char *)wbms);
+      fsp->wbmpx_ptr = NULL;
+      return(UNIXERROR(ERRDOS,ERRnoaccess));
+    }
+    return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
+  } 
+
+  nwritten = write_file(fsp,data,numtowrite);
 
-  if(lp_syncalways(SNUM(cnum)) || write_through)
-    sync_file(fnum);
+  if(lp_syncalways(SNUM(conn)) || write_through)
+    conn->vfs_ops.sync(conn, fsp);
   
-  if (nwritten < numtowrite)
+  if (nwritten < (ssize_t)numtowrite)
+  {
+    if(write_through)
     {
-      if(write_through)        {
-       /* We are returning an error - we can delete the aux struct */
-       if (wbms) free((char *)wbms);
-       Files[fnum].wbmpx_ptr = NULL;
-       return(ERROR(ERRHRD,ERRdiskfull));
-      }
-      return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
+      /* We are returning an error - we can delete the aux struct */
+      if (wbms) free((char *)wbms);
+      fsp->wbmpx_ptr = NULL;
+      return(ERROR(ERRHRD,ERRdiskfull));
     }
+    return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
+  }
 
   /* Increment the total written, if this matches tcount
      we can discard the auxiliary struct (hurrah !) and return a writeC */
   wbms->wr_total_written += nwritten;
   if(wbms->wr_total_written >= tcount)
+  {
+    if (write_through)
     {
-      if (write_through) {
-       outsize = set_message(outbuf,1,0,True);
-       SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
-       send_response = True;
-      }
-
-      free((char *)wbms);
-      Files[fnum].wbmpx_ptr = NULL;
+      outsize = set_message(outbuf,1,0,True);
+      SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
+      send_response = True;
     }
 
+    free((char *)wbms);
+    fsp->wbmpx_ptr = NULL;
+  }
+
   if(send_response)
     return(outsize);
 
@@ -3839,19 +4085,16 @@ int reply_writebs(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a SMBsetattrE
 ****************************************************************************/
-int reply_setattrE(char *inbuf,char *outbuf)
+int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,fnum;
   struct utimbuf unix_times;
   int outsize = 0;
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
   outsize = set_message(outbuf,0,0,True);
 
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
-
-  CHECK_FNUM(fnum,cnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_ERROR(fsp);
 
   /* Convert the DOS times into unix times. Ignore create
      time as UNIX can't set this.
@@ -3867,9 +4110,11 @@ int reply_setattrE(char *inbuf,char *outbuf)
   if ((unix_times.actime == 0) && (unix_times.modtime == 0)) 
   {
     /* Ignore request */
-    DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
-not setting timestamps of 0\n",
-          timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
+    if( DEBUGLVL( 3 ) )
+      {
+      dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
+      dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
+      }
     return(outsize);
   }
   else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) 
@@ -3879,11 +4124,11 @@ not setting timestamps of 0\n",
   }
 
   /* Set the date on this file */
-  if(file_utime(cnum, Files[fnum].name, &unix_times))
+  if(file_utime(conn, fsp->fsp_name, &unix_times))
     return(ERROR(ERRDOS,ERRnoaccess));
   
-  DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
-    timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
+  DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
+            fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
 
   return(outsize);
 }
@@ -3892,32 +4137,29 @@ not setting timestamps of 0\n",
 /****************************************************************************
   reply to a SMBgetattrE
 ****************************************************************************/
-int reply_getattrE(char *inbuf,char *outbuf)
+int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int cnum,fnum;
-  struct stat sbuf;
+  SMB_STRUCT_STAT sbuf;
   int outsize = 0;
   int mode;
+  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
   outsize = set_message(outbuf,11,0,True);
 
-  cnum = SVAL(inbuf,smb_tid);
-  fnum = GETFNUM(inbuf,smb_vwv0);
-
-  CHECK_FNUM(fnum,cnum);
-  CHECK_ERROR(fnum);
+  CHECK_FSP(fsp,conn);
+  CHECK_ERROR(fsp);
 
   /* Do an fstat on this file */
-  if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
+  if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf))
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   
-  mode = dos_mode(cnum,Files[fnum].name,&sbuf);
+  mode = dos_mode(conn,fsp->fsp_name,&sbuf);
   
   /* Convert the times into dos times. Set create
      date to be last modify date as UNIX doesn't save
      this */
-  put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf));
-  put_dos_date2(outbuf,smb_vwv2,get_access_time(&sbuf));
+  put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
+  put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
   put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
   if (mode & aDIR)
     {
@@ -3926,12 +4168,12 @@ int reply_getattrE(char *inbuf,char *outbuf)
     }
   else
     {
-      SIVAL(outbuf,smb_vwv6,sbuf.st_size);
-      SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
+      SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
+      SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
     }
   SSVAL(outbuf,smb_vwv10, mode);
   
-  DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
+  DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
   
   return(outsize);
 }