Prefix VFS API macros with SMB_ for consistency and to avoid problems with VFS_ macro...
[tprouty/samba.git] / source / smbd / reply.c
index 263626dcc1622f169d27ce77f2602d95d31773d8..7a0cc0287a1a2ceb44c3bd3d48a00eb8c9d80000 100644 (file)
@@ -23,7 +23,6 @@
    makes to handle specific protocols
 */
 
-
 #include "includes.h"
 
 /* look in server.c for some explanation of these variables */
@@ -34,15 +33,13 @@ extern char magic_char;
 extern BOOL case_sensitive;
 extern BOOL case_preserve;
 extern BOOL short_case_preserve;
-extern pstring global_myname;
 extern int global_oplock_break;
 unsigned int smb_echo_count = 0;
 
 extern BOOL global_encrypted_passwords_negotiated;
 
-
 /****************************************************************************
-  reply to an special message 
+ Reply to an special message.
 ****************************************************************************/
 
 int reply_special(char *inbuf,char *outbuf)
@@ -90,8 +87,8 @@ int reply_special(char *inbuf,char *outbuf)
                        name2[15] = 0;
                }
 
-               set_local_machine_name(name1);
-               set_remote_machine_name(name2);
+               set_local_machine_name(name1, True);
+               set_remote_machine_name(name2, True);
 
                DEBUG(2,("netbios connect: local=%s remote=%s\n",
                        get_local_machine_name(), get_remote_machine_name() ));
@@ -113,7 +110,7 @@ int reply_special(char *inbuf,char *outbuf)
                reload_services(True);
                reopen_logs();
 
-               claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINTING);
+               claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
 
                already_got_session = True;
                break;
@@ -141,7 +138,6 @@ int reply_special(char *inbuf,char *outbuf)
        return(outsize);
 }
 
-
 /****************************************************************************
  Reply to a tcon.
 ****************************************************************************/
@@ -165,7 +161,7 @@ int reply_tcon(connection_struct *conn,
        *service_buf = *password = *dev = 0;
 
        p = smb_buf(inbuf)+1;
-       p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service), STR_TERMINATE) + 1;
+       p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
        pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
        p += pwlen;
        p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
@@ -208,16 +204,21 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
 {
        fstring service;
        DATA_BLOB password;
-       pstring devicename;
+
+       /* what the cleint thinks the device is */
+       fstring client_devicetype;
+       /* what the server tells the client the share represents */
+       const char *server_devicetype;
        NTSTATUS nt_status;
        uint16 vuid = SVAL(inbuf,smb_uid);
        int passlen = SVAL(inbuf,smb_vwv3);
        pstring path;
        char *p, *q;
        extern BOOL global_encrypted_passwords_negotiated;
+       
        START_PROFILE(SMBtconX);        
 
-       *service = *devicename = 0;
+       *service = *client_devicetype = 0;
 
        /* we might have to close an old one */
        if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
@@ -254,11 +255,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        else
                fstrcpy(service,path);
                
-       p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
+       p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
 
-       DEBUG(4,("Got device type %s\n",devicename));
+       DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
 
-       conn = make_connection(service,password,devicename,vuid,&nt_status);
+       conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
        
        data_blob_clear_free(&password);
 
@@ -267,22 +268,29 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                return ERROR_NT(nt_status);
        }
 
+       if ( IS_IPC(conn) )
+               server_devicetype = "IPC";
+       else if ( IS_PRINT(conn) )
+               server_devicetype = "LPT1:";
+       else 
+               server_devicetype = "A:";
+
        if (Protocol < PROTOCOL_NT1) {
                set_message(outbuf,2,0,True);
                p = smb_buf(outbuf);
-               p += srvstr_push(outbuf, p, devicename, -1, 
+               p += srvstr_push(outbuf, p, server_devicetype, -1, 
                                 STR_TERMINATE|STR_ASCII);
                set_message_end(outbuf,p);
        } else {
                /* NT sets the fstype of IPC$ to the null string */
-               char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
-
+               const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
+               
                set_message(outbuf,3,0,True);
 
                p = smb_buf(outbuf);
-               p += srvstr_push(outbuf, p, devicename, -1, 
+               p += srvstr_push(outbuf, p, server_devicetype, -1, 
                                 STR_TERMINATE|STR_ASCII);
-               p += srvstr_push(outbuf, p, fsname, -1, 
+               p += srvstr_push(outbuf, p, fstype, -1, 
                                 STR_TERMINATE);
                
                set_message_end(outbuf,p);
@@ -307,10 +315,10 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
-
 /****************************************************************************
-  reply to an unknown type
+ Reply to an unknown type.
 ****************************************************************************/
+
 int reply_unknown(char *inbuf,char *outbuf)
 {
        int type;
@@ -322,10 +330,10 @@ int reply_unknown(char *inbuf,char *outbuf)
        return(ERROR_DOS(ERRSRV,ERRunknownsmb));
 }
 
-
 /****************************************************************************
-  reply to an ioctl
+ Reply to an ioctl.
 ****************************************************************************/
+
 int reply_ioctl(connection_struct *conn,
                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -339,8 +347,7 @@ int reply_ioctl(connection_struct *conn,
 
        DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
 
-       switch (ioctl_code)
-       {
+       switch (ioctl_code) {
            case IOCTL_QUERY_JOB_INFO:
                replysize = 32;
                break;
@@ -355,16 +362,14 @@ int reply_ioctl(connection_struct *conn,
        SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
        p = smb_buf(outbuf) + 1;          /* Allow for alignment */
 
-       switch (ioctl_code)
-       {
-           case IOCTL_QUERY_JOB_INFO:              
-          {
-               uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid);
-               SSVAL(p,0,rap_jobid);             /* Job number */
-               srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
-               srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
-               break;
-          }
+       switch (ioctl_code) {
+               case IOCTL_QUERY_JOB_INFO:                  
+               {
+                       SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
+                       srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
+                       srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
+                       break;
+               }
        }
 
        END_PROFILE(SMBioctl);
@@ -372,188 +377,183 @@ int reply_ioctl(connection_struct *conn,
 }
 
 /****************************************************************************
-  reply to a chkpth
+ Reply to a chkpth.
 ****************************************************************************/
+
 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int outsize = 0;
-  int mode;
-  pstring name;
-  BOOL ok = False;
-  BOOL bad_path = False;
-  SMB_STRUCT_STAT sbuf;
-  START_PROFILE(SMBchkpth);
+       int outsize = 0;
+       int mode;
+       pstring name;
+       BOOL ok = False;
+       BOOL bad_path = False;
+       SMB_STRUCT_STAT sbuf;
+       START_PROFILE(SMBchkpth);
 
-  srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
+       srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
 
-  RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
 
-  unix_convert(name,conn,0,&bad_path,&sbuf);
+       unix_convert(name,conn,0,&bad_path,&sbuf);
 
-  mode = SVAL(inbuf,smb_vwv0);
+       mode = SVAL(inbuf,smb_vwv0);
 
-  if (check_name(name,conn)) {
-    if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
-      ok = S_ISDIR(sbuf.st_mode);
-  }
+       if (check_name(name,conn)) {
+               if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
+                       if (!(ok = S_ISDIR(sbuf.st_mode)))
+                               errno = ENOTDIR;
+       }
 
-  if (!ok) {
-    /* We special case this - as when a Windows machine
-       is parsing a path is steps through the components
-       one at a time - if a component fails it expects
-       ERRbadpath, not ERRbadfile.
-     */
-    if(errno == ENOENT) {
-           return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
-    }
+       if (!ok) {
+               /* We special case this - as when a Windows machine
+                       is parsing a path is steps through the components
+                       one at a time - if a component fails it expects
+                       ERRbadpath, not ERRbadfile.
+               */
+               if(errno == ENOENT)
+                       return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
 
-    return(UNIXERROR(ERRDOS,ERRbadpath));
-  }
+               return(UNIXERROR(ERRDOS,ERRbadpath));
+       }
 
-  outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,True);
 
-  DEBUG(3,("chkpth %s mode=%d\n", name, mode));
+       DEBUG(3,("chkpth %s mode=%d\n", name, mode));
 
-  END_PROFILE(SMBchkpth);
-  return(outsize);
+       END_PROFILE(SMBchkpth);
+       return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a getatr
+ Reply to a getatr.
 ****************************************************************************/
+
 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  pstring fname;
-  int outsize = 0;
-  SMB_STRUCT_STAT sbuf;
-  BOOL ok = False;
-  int mode=0;
-  SMB_OFF_T size=0;
-  time_t mtime=0;
-  BOOL bad_path = False;
-  char *p;
-  START_PROFILE(SMBgetatr);
-
-  p = smb_buf(inbuf) + 1;
-  p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
-
-  RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       pstring fname;
+       int outsize = 0;
+       SMB_STRUCT_STAT sbuf;
+       BOOL ok = False;
+       int mode=0;
+       SMB_OFF_T size=0;
+       time_t mtime=0;
+       BOOL bad_path = False;
+       char *p;
+       START_PROFILE(SMBgetatr);
+
+       p = smb_buf(inbuf) + 1;
+       p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
+
+       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
   
-  /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
-     under WfWg - weird! */
-  if (! (*fname))
-  {
-    mode = aHIDDEN | aDIR;
-    if (!CAN_WRITE(conn)) mode |= aRONLY;
-    size = 0;
-    mtime = 0;
-    ok = True;
-  }
-  else
-  {
-    unix_convert(fname,conn,0,&bad_path,&sbuf);
-    if (check_name(fname,conn))
-    {
-      if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
-      {
-        mode = dos_mode(conn,fname,&sbuf);
-        size = sbuf.st_size;
-        mtime = sbuf.st_mtime;
-        if (mode & aDIR)
-          size = 0;
-        ok = True;
-      }
-      else
-        DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
-    }
-  }
+       /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
+               under WfWg - weird! */
+       if (! (*fname)) {
+               mode = aHIDDEN | aDIR;
+               if (!CAN_WRITE(conn))
+                       mode |= aRONLY;
+               size = 0;
+               mtime = 0;
+               ok = True;
+       } else {
+               unix_convert(fname,conn,0,&bad_path,&sbuf);
+               if (check_name(fname,conn)) {
+                       if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
+                               mode = dos_mode(conn,fname,&sbuf);
+                               size = sbuf.st_size;
+                               mtime = sbuf.st_mtime;
+                               if (mode & aDIR)
+                                       size = 0;
+                               ok = True;
+                       } else {
+                               DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
+                       }
+               }
+       }
   
-  if (!ok)
-  {
-    set_bad_path_error(errno, bad_path);
-    END_PROFILE(SMBgetatr);
-    return(UNIXERROR(ERRDOS,ERRbadfile));
-  }
+       if (!ok) {
+               set_bad_path_error(errno, bad_path);
+               END_PROFILE(SMBgetatr);
+               return(UNIXERROR(ERRDOS,ERRbadfile));
+       }
  
-  outsize = set_message(outbuf,10,0,True);
+       outsize = set_message(outbuf,10,0,True);
 
-  SSVAL(outbuf,smb_vwv0,mode);
-  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);
+       SSVAL(outbuf,smb_vwv0,mode);
+       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)
-         SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
+       if (Protocol >= PROTOCOL_NT1)
+               SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
   
-  DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
+       DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
   
-  END_PROFILE(SMBgetatr);
-  return(outsize);
+       END_PROFILE(SMBgetatr);
+       return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a setatr
+ Reply to a setatr.
 ****************************************************************************/
+
 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  pstring fname;
-  int outsize = 0;
-  BOOL ok=False;
-  int mode;
-  time_t mtime;
-  SMB_STRUCT_STAT sbuf;
-  BOOL bad_path = False;
-  char *p;
-
-  START_PROFILE(SMBsetatr);
-
-  p = smb_buf(inbuf) + 1;
-  p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
-  unix_convert(fname,conn,0,&bad_path,&sbuf);
-
-  mode = SVAL(inbuf,smb_vwv0);
-  mtime = make_unix_date3(inbuf+smb_vwv1);
+       pstring fname;
+       int outsize = 0;
+       BOOL ok=False;
+       int mode;
+       time_t mtime;
+       SMB_STRUCT_STAT sbuf;
+       BOOL bad_path = False;
+       char *p;
+
+       START_PROFILE(SMBsetatr);
+
+       p = smb_buf(inbuf) + 1;
+       p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
+       unix_convert(fname,conn,0,&bad_path,&sbuf);
+
+       mode = SVAL(inbuf,smb_vwv0);
+       mtime = make_unix_date3(inbuf+smb_vwv1);
   
-  if (VALID_STAT_OF_DIR(sbuf))
-    mode |= aDIR;
-  else
-    mode &= ~aDIR;
-
-  if (check_name(fname,conn))
-    ok =  (file_chmod(conn,fname,mode,NULL) == 0);
-  if (ok)
-    ok = set_filetime(conn,fname,mtime);
+       if (VALID_STAT_OF_DIR(sbuf))
+               mode |= aDIR;
+       else
+               mode &= ~aDIR;
+
+       if (check_name(fname,conn))
+               ok =  (file_chmod(conn,fname,mode,NULL) == 0);
+       if (ok)
+               ok = set_filetime(conn,fname,mtime);
   
-  if (!ok)
-  {
-    set_bad_path_error(errno, bad_path);
-    END_PROFILE(SMBsetatr);
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
+       if (!ok) {
+               set_bad_path_error(errno, bad_path);
+               END_PROFILE(SMBsetatr);
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
  
-  outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,True);
   
-  DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
+       DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
   
-  END_PROFILE(SMBsetatr);
-  return(outsize);
+       END_PROFILE(SMBsetatr);
+       return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a dskattr
+ Reply to a dskattr.
 ****************************************************************************/
+
 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
        int outsize = 0;
        SMB_BIG_UINT dfree,dsize,bsize;
        START_PROFILE(SMBdskattr);
 
-       conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
+       SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
   
        outsize = set_message(outbuf,5,0,True);
        
@@ -591,621 +591,590 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a search
 Can be called from SMBsearch, SMBffirst or SMBfunique.
+ Reply to a search.
+ Can be called from SMBsearch, SMBffirst or SMBfunique.
 ****************************************************************************/
+
 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  pstring mask;
-  pstring directory;
-  pstring fname;
-  SMB_OFF_T size;
-  int mode;
-  time_t date;
-  int dirtype;
-  int outsize = 0;
-  int numentries = 0;
-  BOOL finished = False;
-  int maxentries;
-  int i;
-  char *p;
-  BOOL ok = False;
-  int status_len;
-  pstring path;
-  char status[21];
-  int dptr_num= -1;
-  BOOL check_descend = False;
-  BOOL expect_close = False;
-  BOOL can_open = True;
-  BOOL bad_path = False;
-  START_PROFILE(SMBsearch);
-
-  *mask = *directory = *fname = 0;
-
-  /* If we were called as SMBffirst then we must expect close. */
-  if(CVAL(inbuf,smb_com) == SMBffirst)
-    expect_close = True;
-  
-  outsize = set_message(outbuf,1,3,True);
-  maxentries = SVAL(inbuf,smb_vwv0); 
-  dirtype = SVAL(inbuf,smb_vwv1);
-  p = smb_buf(inbuf) + 1;
-  p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
-  p++;
-  status_len = SVAL(p, 0);
-  p += 2;
+       pstring mask;
+       pstring directory;
+       pstring fname;
+       SMB_OFF_T size;
+       int mode;
+       time_t date;
+       int dirtype;
+       int outsize = 0;
+       int numentries = 0;
+       BOOL finished = False;
+       int maxentries;
+       int i;
+       char *p;
+       BOOL ok = False;
+       int status_len;
+       pstring path;
+       char status[21];
+       int dptr_num= -1;
+       BOOL check_descend = False;
+       BOOL expect_close = False;
+       BOOL can_open = True;
+       BOOL bad_path = False;
+       START_PROFILE(SMBsearch);
+
+       *mask = *directory = *fname = 0;
+
+       /* If we were called as SMBffirst then we must expect close. */
+       if(CVAL(inbuf,smb_com) == SMBffirst)
+               expect_close = True;
   
-  /* dirtype &= ~aDIR; */
+       outsize = set_message(outbuf,1,3,True);
+       maxentries = SVAL(inbuf,smb_vwv0); 
+       dirtype = SVAL(inbuf,smb_vwv1);
+       p = smb_buf(inbuf) + 1;
+       p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
+       p++;
+       status_len = SVAL(p, 0);
+       p += 2;
   
-  if (status_len == 0)
-  {
-    SMB_STRUCT_STAT sbuf;
-    pstring dir2;
-
-    pstrcpy(directory,path);
-    pstrcpy(dir2,path);
-    unix_convert(directory,conn,0,&bad_path,&sbuf);
-    unix_format(dir2);
-
-    if (!check_name(directory,conn))
-      can_open = False;
-
-    p = strrchr_m(dir2,'/');
-    if (p == NULL) 
-    {
-      pstrcpy(mask,dir2);
-      *dir2 = 0;
-    }
-    else
-    {
-      *p = 0;
-      pstrcpy(mask,p+1);
-    }
-
-    p = strrchr_m(directory,'/');
-    if (!p) 
-      *directory = 0;
-    else
-      *p = 0;
-
-    if (strlen(directory) == 0)
-      pstrcpy(directory,"./");
-    memset((char *)status,'\0',21);
-    SCVAL(status,0,dirtype);
-  }
-  else
-  {
-    memcpy(status,p,21);
-    dirtype = CVAL(status,0) & 0x1F;
-    conn->dirptr = dptr_fetch(status+12,&dptr_num);      
-    if (!conn->dirptr)
-      goto SearchEmpty;
-    string_set(&conn->dirpath,dptr_path(dptr_num));
-    fstrcpy(mask, dptr_wcard(dptr_num));
-  }
-
-  if (can_open)
-  {
-    p = smb_buf(outbuf) + 3;
-      
-    ok = True;
+       /* dirtype &= ~aDIR; */
+
+       if (status_len == 0) {
+               SMB_STRUCT_STAT sbuf;
+               pstring dir2;
+
+               pstrcpy(directory,path);
+               pstrcpy(dir2,path);
+               unix_convert(directory,conn,0,&bad_path,&sbuf);
+               unix_format(dir2);
+
+               if (!check_name(directory,conn))
+                       can_open = False;
+
+               p = strrchr_m(dir2,'/');
+               if (p == NULL) {
+                       pstrcpy(mask,dir2);
+                       *dir2 = 0;
+               } else {
+                       *p = 0;
+                       pstrcpy(mask,p+1);
+               }
+
+               p = strrchr_m(directory,'/');
+               if (!p) 
+                       *directory = 0;
+               else
+                       *p = 0;
+
+               if (strlen(directory) == 0)
+                       pstrcpy(directory,".");
+               memset((char *)status,'\0',21);
+               SCVAL(status,0,(dirtype & 0x1F));
+       } else {
+               int status_dirtype;
+
+               memcpy(status,p,21);
+               status_dirtype = CVAL(status,0) & 0x1F;
+               if (status_dirtype != (dirtype & 0x1F))
+                       dirtype = status_dirtype;
+
+               conn->dirptr = dptr_fetch(status+12,&dptr_num);      
+               if (!conn->dirptr)
+                       goto SearchEmpty;
+               string_set(&conn->dirpath,dptr_path(dptr_num));
+               pstrcpy(mask, dptr_wcard(dptr_num));
+       }
+
+       if (can_open) {
+               p = smb_buf(outbuf) + 3;
+               ok = True;
      
-    if (status_len == 0)
-    {
-      dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
-      if (dptr_num < 0)
-      {
-        if(dptr_num == -2)
-        {
-          set_bad_path_error(errno, bad_path);
-          END_PROFILE(SMBsearch);
-          return (UNIXERROR(ERRDOS,ERRnofids));
-        }
-               END_PROFILE(SMBsearch);
-        return ERROR_DOS(ERRDOS,ERRnofids);
-      }
-      dptr_set_wcard(dptr_num, strdup(mask));
-    }
-
-    DEBUG(4,("dptr_num is %d\n",dptr_num));
-
-    if (ok)
-    {
-      if ((dirtype&0x1F) == aVOLID)
-      {          
-        memcpy(p,status,21);
-        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;
-        else
-          numentries = 0;
-        p += DIR_STRUCT_SIZE;
-      }
-      else 
-      {
-        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(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
-          if (!finished)
-          {
-            memcpy(p,status,21);
-            make_dir_struct(p,mask,fname,size,mode,date);
-            dptr_fill(p+12,dptr_num);
-            numentries++;
-         }
-         p += DIR_STRUCT_SIZE;
-        }
-      }
-       } /* if (ok ) */
-  }
+               if (status_len == 0) {
+                       dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
+                       if (dptr_num < 0) {
+                               if(dptr_num == -2) {
+                                       set_bad_path_error(errno, bad_path);
+                                       END_PROFILE(SMBsearch);
+                                       return (UNIXERROR(ERRDOS,ERRnofids));
+                               }
+                               END_PROFILE(SMBsearch);
+                               return ERROR_DOS(ERRDOS,ERRnofids);
+                       }
+                       dptr_set_wcard(dptr_num, strdup(mask));
+                       dptr_set_attr(dptr_num, dirtype);
+               } else {
+                       dirtype = dptr_attr(dptr_num);
+               }
+
+               DEBUG(4,("dptr_num is %d\n",dptr_num));
+
+               if (ok) {
+                       if ((dirtype&0x1F) == aVOLID) {   
+                               memcpy(p,status,21);
+                               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;
+                               else
+                                       numentries = 0;
+                               p += DIR_STRUCT_SIZE;
+                       } else {
+                               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(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
+                                       if (!finished) {
+                                               memcpy(p,status,21);
+                                               make_dir_struct(p,mask,fname,size,mode,date);
+                                               dptr_fill(p+12,dptr_num);
+                                               numentries++;
+                                       }
+                                       p += DIR_STRUCT_SIZE;
+                               }
+                       }
+               } /* if (ok ) */
+       }
 
 
   SearchEmpty:
 
-  if (numentries == 0 || !ok)
-  {
-    SCVAL(outbuf,smb_rcls,ERRDOS);
-    SSVAL(outbuf,smb_err,ERRnofiles);
-    dptr_close(&dptr_num);
-  }
-
-  /* If we were called as SMBffirst with smb_search_id == NULL
-     and no entries were found then return error and close dirptr 
-     (X/Open spec) */
-
-  if(ok && expect_close && numentries == 0 && status_len == 0)
-  {
-    SCVAL(outbuf,smb_rcls,ERRDOS);
-    SSVAL(outbuf,smb_err,ERRnofiles);
-    /* Also close the dptr - we know it's gone */
-    dptr_close(&dptr_num);
-  }
-
-  /* If we were called as SMBfunique, then we can close the dirptr now ! */
-  if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
-    dptr_close(&dptr_num);
-
-  SSVAL(outbuf,smb_vwv0,numentries);
-  SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
-  SCVAL(smb_buf(outbuf),0,5);
-  SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
-
-  if (Protocol >= PROTOCOL_NT1)
-    SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
+       if (numentries == 0 || !ok) {
+               SCVAL(outbuf,smb_rcls,ERRDOS);
+               SSVAL(outbuf,smb_err,ERRnofiles);
+               dptr_close(&dptr_num);
+       }
+
+       /* If we were called as SMBffirst with smb_search_id == NULL
+               and no entries were found then return error and close dirptr 
+               (X/Open spec) */
+
+       if(ok && expect_close && numentries == 0 && status_len == 0) {
+               SCVAL(outbuf,smb_rcls,ERRDOS);
+               SSVAL(outbuf,smb_err,ERRnofiles);
+               /* Also close the dptr - we know it's gone */
+               dptr_close(&dptr_num);
+       }
+
+       /* If we were called as SMBfunique, then we can close the dirptr now ! */
+       if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
+               dptr_close(&dptr_num);
+
+       SSVAL(outbuf,smb_vwv0,numentries);
+       SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
+       SCVAL(smb_buf(outbuf),0,5);
+       SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
+
+       if (Protocol >= PROTOCOL_NT1)
+               SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
   
-  outsize += DIR_STRUCT_SIZE*numentries;
-  smb_setlen(outbuf,outsize - 4);
+       outsize += DIR_STRUCT_SIZE*numentries;
+       smb_setlen(outbuf,outsize - 4);
   
-  if ((! *directory) && dptr_path(dptr_num))
-    slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
+       if ((! *directory) && dptr_path(dptr_num))
+               slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
 
-  DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
-        smb_fn_name(CVAL(inbuf,smb_com)), 
-        mask, directory, dirtype, numentries, maxentries ) );
+       DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
+               smb_fn_name(CVAL(inbuf,smb_com)), 
+               mask, directory, dirtype, numentries, maxentries ) );
 
-  END_PROFILE(SMBsearch);
-  return(outsize);
+       END_PROFILE(SMBsearch);
+       return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a fclose (stop directory search)
+ Reply to a fclose (stop directory search).
 ****************************************************************************/
+
 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int outsize = 0;
-  int status_len;
-  pstring path;
-  char status[21];
-  int dptr_num= -2;
-  char *p;
+       int outsize = 0;
+       int status_len;
+       pstring path;
+       char status[21];
+       int dptr_num= -2;
+       char *p;
 
-  START_PROFILE(SMBfclose);
+       START_PROFILE(SMBfclose);
 
-  outsize = set_message(outbuf,1,0,True);
-  p = smb_buf(inbuf) + 1;
-  p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
-  p++;
-  status_len = SVAL(p,0);
-  p += 2;
+       outsize = set_message(outbuf,1,0,True);
+       p = smb_buf(inbuf) + 1;
+       p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
+       p++;
+       status_len = SVAL(p,0);
+       p += 2;
 
-  if (status_len == 0) {
-    END_PROFILE(SMBfclose);
-    return ERROR_DOS(ERRSRV,ERRsrverror);
-  }
+       if (status_len == 0) {
+               END_PROFILE(SMBfclose);
+               return ERROR_DOS(ERRSRV,ERRsrverror);
+       }
 
-  memcpy(status,p,21);
+       memcpy(status,p,21);
 
-  if(dptr_fetch(status+12,&dptr_num)) {
-    /*  Close the dptr - we know it's gone */
-    dptr_close(&dptr_num);
-  }
+       if(dptr_fetch(status+12,&dptr_num)) {
+               /*  Close the dptr - we know it's gone */
+               dptr_close(&dptr_num);
+       }
 
-  SSVAL(outbuf,smb_vwv0,0);
+       SSVAL(outbuf,smb_vwv0,0);
 
-  DEBUG(3,("search close\n"));
+       DEBUG(3,("search close\n"));
 
-  END_PROFILE(SMBfclose);
-  return(outsize);
+       END_PROFILE(SMBfclose);
+       return(outsize);
 }
 
-
 /****************************************************************************
-  reply to an open
+ Reply to an open.
 ****************************************************************************/
 
 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  pstring fname;
-  int outsize = 0;
-  int fmode=0;
-  int share_mode;
-  SMB_OFF_T size = 0;
-  time_t mtime=0;
-  mode_t unixmode;
-  int rmode=0;
-  SMB_STRUCT_STAT sbuf;
-  BOOL bad_path = False;
-  files_struct *fsp;
-  int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
-  START_PROFILE(SMBopen);
+       pstring fname;
+       int outsize = 0;
+       int fmode=0;
+       int share_mode;
+       SMB_OFF_T size = 0;
+       time_t mtime=0;
+       mode_t unixmode;
+       int rmode=0;
+       SMB_STRUCT_STAT sbuf;
+       BOOL bad_path = False;
+       files_struct *fsp;
+       int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+       START_PROFILE(SMBopen);
  
-  share_mode = SVAL(inbuf,smb_vwv0);
+       share_mode = SVAL(inbuf,smb_vwv0);
 
-  srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
+       srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
 
-  RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
-  unix_convert(fname,conn,0,&bad_path,&sbuf);
+       unix_convert(fname,conn,0,&bad_path,&sbuf);
     
-  unixmode = unix_mode(conn,aARCH,fname);
+       unixmode = unix_mode(conn,aARCH,fname);
       
-  fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
-                   unixmode, oplock_request,&rmode,NULL);
-
-  if (!fsp)
-  {
-    set_bad_path_error(errno, bad_path);
-    END_PROFILE(SMBopen);
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
-
-  size = sbuf.st_size;
-  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(fsp,False);
-    END_PROFILE(SMBopen);
-    return ERROR_DOS(ERRDOS,ERRnoaccess);
-  }
+       fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
+                       unixmode, oplock_request,&rmode,NULL);
+
+       if (!fsp) {
+               set_bad_path_error(errno, bad_path);
+               END_PROFILE(SMBopen);
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
+
+       size = sbuf.st_size;
+       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(fsp,False);
+               END_PROFILE(SMBopen);
+               return ERROR_DOS(ERRDOS,ERRnoaccess);
+       }
   
-  outsize = set_message(outbuf,7,0,True);
-  SSVAL(outbuf,smb_vwv0,fsp->fnum);
-  SSVAL(outbuf,smb_vwv1,fmode);
-  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(conn))) {
-    SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
-  }
+       outsize = set_message(outbuf,7,0,True);
+       SSVAL(outbuf,smb_vwv0,fsp->fnum);
+       SSVAL(outbuf,smb_vwv1,fmode);
+       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(conn)))
+               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
     
-  if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
-    SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
-  END_PROFILE(SMBopen);
-  return(outsize);
+       if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       END_PROFILE(SMBopen);
+       return(outsize);
 }
 
-
 /****************************************************************************
-  reply to an open and X
+ Reply to an open and X.
 ****************************************************************************/
+
 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
-  pstring fname;
-  int smb_mode = SVAL(inbuf,smb_vwv3);
-  int smb_attr = SVAL(inbuf,smb_vwv5);
-  /* Breakout the oplock request bits so we can set the
-     reply bits separately. */
-  BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
-  BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
-  BOOL oplock_request = ex_oplock_request | core_oplock_request;
+       pstring fname;
+       int smb_mode = SVAL(inbuf,smb_vwv3);
+       int smb_attr = SVAL(inbuf,smb_vwv5);
+       /* Breakout the oplock request bits so we can set the
+               reply bits separately. */
+       BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
+       BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+       BOOL oplock_request = ex_oplock_request | core_oplock_request;
 #if 0
-  int open_flags = SVAL(inbuf,smb_vwv2);
-  int smb_sattr = SVAL(inbuf,smb_vwv4); 
-  uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
+       int open_flags = SVAL(inbuf,smb_vwv2);
+       int smb_sattr = SVAL(inbuf,smb_vwv4); 
+       uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
 #endif
-  int smb_ofun = SVAL(inbuf,smb_vwv8);
-  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;
-  START_PROFILE(SMBopenX);
-
-  /* If it's an IPC, pass off the pipe handler. */
-  if (IS_IPC(conn)) {
-    if (lp_nt_pipe_support()) {
-           END_PROFILE(SMBopenX);
-           return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
-    } else {
-               END_PROFILE(SMBopenX);
-        return ERROR_DOS(ERRSRV,ERRaccess);
-    }
-  }
+       int smb_ofun = SVAL(inbuf,smb_vwv8);
+       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;
+       START_PROFILE(SMBopenX);
+
+       /* If it's an IPC, pass off the pipe handler. */
+       if (IS_IPC(conn)) {
+               if (lp_nt_pipe_support()) {
+                       END_PROFILE(SMBopenX);
+                       return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
+               } else {
+                       END_PROFILE(SMBopenX);
+                       return ERROR_DOS(ERRSRV,ERRaccess);
+               }
+       }
 
-  /* XXXX we need to handle passed times, sattr and flags */
-  srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
+       /* XXXX we need to handle passed times, sattr and flags */
+       srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
 
-  RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
-  unix_convert(fname,conn,0,&bad_path,&sbuf);
+       unix_convert(fname,conn,0,&bad_path,&sbuf);
     
-  unixmode = unix_mode(conn,smb_attr | aARCH, fname);
+       unixmode = unix_mode(conn,smb_attr | aARCH, fname);
       
-  fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
-                      oplock_request, &rmode,&smb_action);
+       fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
+                       oplock_request, &rmode,&smb_action);
       
-  if (!fsp)
-  {
-    set_bad_path_error(errno, bad_path);
-    END_PROFILE(SMBopenX);
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
-
-  size = sbuf.st_size;
-  fmode = dos_mode(conn,fname,&sbuf);
-  mtime = sbuf.st_mtime;
-  if (fmode & aDIR) {
-    close_file(fsp,False);
-    END_PROFILE(SMBopenX);
-    return ERROR_DOS(ERRDOS,ERRnoaccess);
-  }
-
-  /* If the caller set the extended oplock request bit
-     and we granted one (by whatever means) - set the
-     correct bit for extended oplock reply.
-   */
-
-  if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
-    smb_action |= EXTENDED_OPLOCK_GRANTED;
-  }
-
-  if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
-    smb_action |= EXTENDED_OPLOCK_GRANTED;
-  }
-
-  /* If the caller set the core oplock request bit
-     and we granted one (by whatever means) - set the
-     correct bit for core oplock reply.
-   */
-
-  if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
-    SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
-  }
-
-  if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
-    SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
-  }
-
-  set_message(outbuf,15,0,True);
-  SSVAL(outbuf,smb_vwv2,fsp->fnum);
-  SSVAL(outbuf,smb_vwv3,fmode);
-  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);
-
-  END_PROFILE(SMBopenX);
-  return chain_reply(inbuf,outbuf,length,bufsize);
-}
+       if (!fsp) {
+               set_bad_path_error(errno, bad_path);
+               END_PROFILE(SMBopenX);
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
 
+       size = sbuf.st_size;
+       fmode = dos_mode(conn,fname,&sbuf);
+       mtime = sbuf.st_mtime;
+       if (fmode & aDIR) {
+               close_file(fsp,False);
+               END_PROFILE(SMBopenX);
+               return ERROR_DOS(ERRDOS,ERRnoaccess);
+       }
+
+       /* If the caller set the extended oplock request bit
+               and we granted one (by whatever means) - set the
+               correct bit for extended oplock reply.
+       */
+
+       if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
+               smb_action |= EXTENDED_OPLOCK_GRANTED;
+
+       if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+               smb_action |= EXTENDED_OPLOCK_GRANTED;
+
+       /* If the caller set the core oplock request bit
+               and we granted one (by whatever means) - set the
+               correct bit for core oplock reply.
+       */
+
+       if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
+               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+
+       if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+
+       set_message(outbuf,15,0,True);
+       SSVAL(outbuf,smb_vwv2,fsp->fnum);
+       SSVAL(outbuf,smb_vwv3,fmode);
+       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);
+
+       END_PROFILE(SMBopenX);
+       return chain_reply(inbuf,outbuf,length,bufsize);
+}
 
 /****************************************************************************
-  reply to a SMBulogoffX
+ Reply to a SMBulogoffX.
 ****************************************************************************/
+
 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);
-  START_PROFILE(SMBulogoffX);
+       uint16 vuid = SVAL(inbuf,smb_uid);
+       user_struct *vuser = get_valid_user_struct(vuid);
+       START_PROFILE(SMBulogoffX);
 
-  if(vuser == 0) {
-    DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
-  }
+       if(vuser == 0)
+               DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
 
-  /* in user level security we are supposed to close any files
-     open by this user */
-  if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
-         file_close_user(vuid);
-  }
+       /* in user level security we are supposed to close any files
+               open by this user */
+       if ((vuser != 0) && (lp_security() != SEC_SHARE))
+               file_close_user(vuid);
 
-  invalidate_vuid(vuid);
+       invalidate_vuid(vuid);
 
-  set_message(outbuf,2,0,True);
+       set_message(outbuf,2,0,True);
 
-  DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
+       DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
 
-  END_PROFILE(SMBulogoffX);
-  return chain_reply(inbuf,outbuf,length,bufsize);
+       END_PROFILE(SMBulogoffX);
+       return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
-
 /****************************************************************************
-  reply to a mknew or a create
+ Reply to a mknew or a create.
 ****************************************************************************/
+
 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  pstring fname;
-  int com;
-  int outsize = 0;
-  int createmode;
-  mode_t unixmode;
-  int ofun = 0;
-  BOOL bad_path = False;
-  files_struct *fsp;
-  int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
-  SMB_STRUCT_STAT sbuf;
-  START_PROFILE(SMBcreate);
+       pstring fname;
+       int com;
+       int outsize = 0;
+       int createmode;
+       mode_t unixmode;
+       int ofun = 0;
+       BOOL bad_path = False;
+       files_struct *fsp;
+       int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+       SMB_STRUCT_STAT sbuf;
+       START_PROFILE(SMBcreate);
  
-  com = SVAL(inbuf,smb_com);
+       com = SVAL(inbuf,smb_com);
 
-  createmode = SVAL(inbuf,smb_vwv0);
-  srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
+       createmode = SVAL(inbuf,smb_vwv0);
+       srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
 
-  RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
-  unix_convert(fname,conn,0,&bad_path,&sbuf);
+       unix_convert(fname,conn,0,&bad_path,&sbuf);
 
-  if (createmode & aVOLID) {
-      DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
-  }
+       if (createmode & aVOLID)
+               DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
   
-  unixmode = unix_mode(conn,createmode,fname);
+       unixmode = unix_mode(conn,createmode,fname);
   
-  if(com == SMBmknew)
-  {
-    /* We should fail if file exists. */
-    ofun = FILE_CREATE_IF_NOT_EXIST;
-  }
-  else
-  {
-    /* SMBcreate - Create if file doesn't exist, truncate if it does. */
-    ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
-  }
-
-  /* Open file in dos compatibility share mode. */
-  fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
-                   ofun, unixmode, oplock_request, NULL, NULL);
+       if(com == SMBmknew) {
+               /* We should fail if file exists. */
+               ofun = FILE_CREATE_IF_NOT_EXIST;
+       } else {
+               /* SMBcreate - Create if file doesn't exist, truncate if it does. */
+               ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
+       }
+
+       /* Open file in dos compatibility share mode. */
+       fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
+                       ofun, unixmode, oplock_request, NULL, NULL);
   
-  if (!fsp)
-  {
-    set_bad_path_error(errno, bad_path);
-    END_PROFILE(SMBcreate);
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
+       if (!fsp) {
+               set_bad_path_error(errno, bad_path);
+               END_PROFILE(SMBcreate);
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
  
-  outsize = set_message(outbuf,1,0,True);
-  SSVAL(outbuf,smb_vwv0,fsp->fnum);
+       outsize = set_message(outbuf,1,0,True);
+       SSVAL(outbuf,smb_vwv0,fsp->fnum);
 
-  if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
-    SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
-  }
+       if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
  
-  if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
-    SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
  
-  DEBUG( 2, ( "new file %s\n", fname ) );
-  DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
-        fname, fsp->fd, createmode, (int)unixmode ) );
+       DEBUG( 2, ( "new file %s\n", fname ) );
+       DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
 
-  END_PROFILE(SMBcreate);
-  return(outsize);
+       END_PROFILE(SMBcreate);
+       return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a create temporary file
+ Reply to a create temporary file.
 ****************************************************************************/
+
 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  pstring fname;
-  int outsize = 0;
-  int createmode;
-  mode_t unixmode;
-  BOOL bad_path = False;
-  files_struct *fsp;
-  int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
-  int tmpfd;
-  SMB_STRUCT_STAT sbuf;
-  char *p, *s;
-
-  START_PROFILE(SMBctemp);
-
-  createmode = SVAL(inbuf,smb_vwv0);
-  srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
-  pstrcat(fname,"\\TMXXXXXX");
-
-  RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
-
-  unix_convert(fname,conn,0,&bad_path,&sbuf);
+       pstring fname;
+       int outsize = 0;
+       int createmode;
+       mode_t unixmode;
+       BOOL bad_path = False;
+       files_struct *fsp;
+       int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+       int tmpfd;
+       SMB_STRUCT_STAT sbuf;
+       char *p, *s;
+
+       START_PROFILE(SMBctemp);
+
+       createmode = SVAL(inbuf,smb_vwv0);
+       srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
+       pstrcat(fname,"\\TMXXXXXX");
+
+       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+
+       unix_convert(fname,conn,0,&bad_path,&sbuf);
   
-  unixmode = unix_mode(conn,createmode,fname);
+       unixmode = unix_mode(conn,createmode,fname);
   
-  tmpfd = smb_mkstemp(fname);
-  if (tmpfd == -1) {
-      END_PROFILE(SMBctemp);
-      return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
-
-  vfs_stat(conn,fname,&sbuf);
-
-  /* Open file in dos compatibility share mode. */
-  /* We should fail if file does not exist. */
-  fsp = open_file_shared(conn,fname,&sbuf,
-                        SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
-                        FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
-                        unixmode, oplock_request, NULL, NULL);
-
-  /* close fd from smb_mkstemp() */
-  close(tmpfd);
-
-  if (!fsp) {
-    set_bad_path_error(errno, bad_path);
-    END_PROFILE(SMBctemp);
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
-
-  outsize = set_message(outbuf,1,0,True);
-  SSVAL(outbuf,smb_vwv0,fsp->fnum);
-
-  /* the returned filename is relative to the directory */
-  s = strrchr_m(fname, '/');
-  if (!s) {
-         s = fname;
-  } else {
-         s++;
-  }
-
-  p = smb_buf(outbuf);
-  SSVALS(p, 0, -1); /* what is this? not in spec */
-  SSVAL(p, 2, strlen(s));
-  p += 4;
-  p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
-  outsize = set_message_end(outbuf, p);
-
-  if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
-         SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
-  }
+       tmpfd = smb_mkstemp(fname);
+       if (tmpfd == -1) {
+               END_PROFILE(SMBctemp);
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
+
+       SMB_VFS_STAT(conn,fname,&sbuf);
+
+       /* Open file in dos compatibility share mode. */
+       /* We should fail if file does not exist. */
+       fsp = open_file_shared(conn,fname,&sbuf,
+               SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
+               FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
+               unixmode, oplock_request, NULL, NULL);
+
+       /* close fd from smb_mkstemp() */
+       close(tmpfd);
+
+       if (!fsp) {
+               set_bad_path_error(errno, bad_path);
+               END_PROFILE(SMBctemp);
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
+
+       outsize = set_message(outbuf,1,0,True);
+       SSVAL(outbuf,smb_vwv0,fsp->fnum);
+
+       /* the returned filename is relative to the directory */
+       s = strrchr_m(fname, '/');
+       if (!s)
+               s = fname;
+       else
+               s++;
+
+       p = smb_buf(outbuf);
+       SSVALS(p, 0, -1); /* what is this? not in spec */
+       SSVAL(p, 2, strlen(s));
+       p += 4;
+       p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
+       outsize = set_message_end(outbuf, p);
+
+       if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
   
-  if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
-         SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
 
-  DEBUG( 2, ( "created temp file %s\n", fname ) );
-  DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
-        fname, fsp->fd, createmode, (int)unixmode ) );
+       DEBUG( 2, ( "created temp file %s\n", fname ) );
+       DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
+                       fname, fsp->fd, createmode, (int)unixmode ) );
 
-  END_PROFILE(SMBctemp);
-  return(outsize);
+       END_PROFILE(SMBctemp);
+       return(outsize);
 }
 
 /*******************************************************************
@@ -1258,7 +1227,7 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
        if (!CAN_WRITE(conn))
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
 
-       if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
+       if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0)
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        fmode = dos_mode(conn,fname,&sbuf);
@@ -1280,10 +1249,13 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
 
        if (!fsp) {
                NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
-               if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+               if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
+                       ret = unix_ERR_ntstatus;
+               else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
                        ret = NT_STATUS_SHARING_VIOLATION;
                unix_ERR_class = 0;
                unix_ERR_code = 0;
+               unix_ERR_ntstatus = NT_STATUS_OK;
                return ret;
        }
        close_file(fsp,False);
@@ -1341,12 +1313,12 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
                error = can_delete(directory,conn,dirtype);
                if (!NT_STATUS_IS_OK(error)) return error;
 
-               if (vfs_unlink(conn,directory) == 0) {
+               if (SMB_VFS_UNLINK(conn,directory) == 0) {
                        count++;
                }
        } else {
                void *dirptr = NULL;
-               char *dname;
+               const char *dname;
                
                if (check_name(directory,conn))
                        dirptr = OpenDir(conn, directory, True);
@@ -1371,7 +1343,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
                                slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
                                error = can_delete(fname,conn,dirtype);
                                if (!NT_STATUS_IS_OK(error)) continue;
-                               if (vfs_unlink(conn,fname) == 0) count++;
+                               if (SMB_VFS_UNLINK(conn,fname) == 0) count++;
                                DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
                        }
                        CloseDir(dirptr);
@@ -1433,17 +1405,70 @@ void fail_readraw(void)
        exit_server(errstr);
 }
 
+/****************************************************************************
+ Use sendfile in readbraw.
+****************************************************************************/
+
+void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
+               ssize_t mincount, char *outbuf)
+{
+       ssize_t ret=0;
+
+#if defined(WITH_SENDFILE)
+       /*
+        * We can only use sendfile on a non-chained packet and on a file
+        * that is exclusively oplocked. reply_readbraw has already checked the length.
+        */
+
+       if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
+                       EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
+               DATA_BLOB header;
+
+               _smb_setlen(outbuf,nread);
+               header.data = outbuf;
+               header.length = 4;
+               header.free = NULL;
+
+               if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
+                       /*
+                        * Special hack for broken Linux with no 64 bit clean sendfile. If we
+                        * return ENOSYS then pretend we just got a normal read.
+                        */
+                       if (errno == ENOSYS)
+                               goto normal_read;
+
+                       DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
+                               fsp->fsp_name, strerror(errno) ));
+                       exit_server("send_file_readbraw sendfile failed");
+               }
+
+       }
+
+  normal_read:
+#endif
+
+       if (nread > 0) {
+               ret = read_file(fsp,outbuf+4,startpos,nread);
+               if (ret < mincount)
+                       ret = 0;
+       }
+
+       _smb_setlen(outbuf,ret);
+       if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
+               fail_readraw();
+}
+
 /****************************************************************************
  Reply to a readbraw (core+ protocol).
 ****************************************************************************/
 
 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
 {
+       extern struct current_user current_user;
        ssize_t maxcount,mincount;
        size_t nread = 0;
        SMB_OFF_T startpos;
        char *header = outbuf;
-       ssize_t ret=0;
        files_struct *fsp;
        START_PROFILE(SMBreadbraw);
 
@@ -1480,7 +1505,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
 
        flush_write_cache(fsp, READRAW_FLUSH);
 
-       startpos = IVAL(inbuf,smb_vwv1);
+       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
        if(CVAL(inbuf,smb_wct) == 10) {
                /*
                 * This is a large offset (64 bit) read.
@@ -1529,7 +1554,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
   
                if (size < sizeneeded) {
                        SMB_STRUCT_STAT st;
-                       if (vfs_fstat(fsp,fsp->fd,&st) == 0)
+                       if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
                                size = st.st_size;
                        if (!fsp->can_write) 
                                fsp->size = size;
@@ -1547,15 +1572,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
        DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
                                (int)maxcount, (int)mincount, (int)nread ) );
   
-       if (nread > 0) {
-               ret = read_file(fsp,header+4,startpos,nread);
-               if (ret < mincount)
-                       ret = 0;
-       }
-
-       _smb_setlen(header,ret);
-       if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
-               fail_readraw();
+       send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
 
        DEBUG(5,("readbraw finished\n"));
        END_PROFILE(SMBreadbraw);
@@ -1563,8 +1580,9 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
 }
 
 /****************************************************************************
-  reply to a lockread (core+ protocol)
+ Reply to a lockread (core+ protocol).
 ****************************************************************************/
+
 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
 {
        ssize_t nread = -1;
@@ -1582,7 +1600,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
        release_level_2_oplocks_on_change(fsp);
 
        numtoread = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL(inbuf,smb_vwv2);
+       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
   
        outsize = set_message(outbuf,5,3,True);
        numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
@@ -1599,15 +1617,17 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
                         (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
 
        if (NT_STATUS_V(status)) {
-               if (lp_blocking_locks(SNUM(conn))) {
+               if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
                        /*
                         * 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))
+                       if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
+                                                               (SMB_BIG_UINT)numtoread)) {
                                END_PROFILE(SMBlockread);
-                       return -1;
+                               return -1;
+                       }
                }
                END_PROFILE(SMBlockread);
                return ERROR_NT(status);
@@ -1632,132 +1652,209 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a read
+ Reply to a read.
 ****************************************************************************/
 
 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
 {
-  size_t numtoread;
-  ssize_t nread = 0;
-  char *data;
-  SMB_OFF_T startpos;
-  int outsize = 0;
-  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
-  START_PROFILE(SMBread);
-
-  CHECK_FSP(fsp,conn);
-  CHECK_READ(fsp);
+       size_t numtoread;
+       ssize_t nread = 0;
+       char *data;
+       SMB_OFF_T startpos;
+       int outsize = 0;
+       files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+       START_PROFILE(SMBread);
 
-  numtoread = SVAL(inbuf,smb_vwv1);
-  startpos = IVAL(inbuf,smb_vwv2);
+       CHECK_FSP(fsp,conn);
+       CHECK_READ(fsp);
 
+       numtoread = SVAL(inbuf,smb_vwv1);
+       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
 
-  outsize = set_message(outbuf,5,3,True);
-  numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
-  data = smb_buf(outbuf) + 3;
+       outsize = set_message(outbuf,5,3,True);
+       numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
+       data = smb_buf(outbuf) + 3;
   
-  if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
-    END_PROFILE(SMBread);
-    return ERROR_DOS(ERRDOS,ERRlock);
-  }
-
-  if (numtoread > 0)
-    nread = read_file(fsp,data,startpos,numtoread);
-
-  if (nread < 0) {
-    END_PROFILE(SMBread);
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
+       if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+               END_PROFILE(SMBread);
+               return ERROR_DOS(ERRDOS,ERRlock);
+       }
+
+       if (numtoread > 0)
+               nread = read_file(fsp,data,startpos,numtoread);
+
+       if (nread < 0) {
+               END_PROFILE(SMBread);
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
   
-  outsize += nread;
-  SSVAL(outbuf,smb_vwv0,nread);
-  SSVAL(outbuf,smb_vwv5,nread+3);
-  SCVAL(smb_buf(outbuf),0,1);
-  SSVAL(smb_buf(outbuf),1,nread);
+       outsize += nread;
+       SSVAL(outbuf,smb_vwv0,nread);
+       SSVAL(outbuf,smb_vwv5,nread+3);
+       SCVAL(smb_buf(outbuf),0,1);
+       SSVAL(smb_buf(outbuf),1,nread);
   
-  DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
-            fsp->fnum, (int)numtoread, (int)nread ) );
+       DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
+               fsp->fnum, (int)numtoread, (int)nread ) );
 
-  END_PROFILE(SMBread);
-  return(outsize);
+       END_PROFILE(SMBread);
+       return(outsize);
 }
 
+/****************************************************************************
+ Reply to a read and X - possibly using sendfile.
+****************************************************************************/
+
+int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, 
+               files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
+{
+       ssize_t nread = -1;
+       char *data = smb_buf(outbuf);
+
+#if defined(WITH_SENDFILE)
+       /*
+        * We can only use sendfile on a non-chained packet and on a file
+        * that is exclusively oplocked.
+        */
+
+       if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
+                       lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
+               SMB_STRUCT_STAT sbuf;
+               DATA_BLOB header;
+
+               if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
+                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+
+               if (startpos > sbuf.st_size)
+                       goto normal_read;
+
+               if (smb_maxcnt > (sbuf.st_size - startpos))
+                       smb_maxcnt = (sbuf.st_size - startpos);
+
+               if (smb_maxcnt == 0)
+                       goto normal_read;
+
+               /* 
+                * Set up the packet header before send. We
+                * assume here the sendfile will work (get the
+                * correct amount of data).
+                */
+
+               SSVAL(outbuf,smb_vwv5,smb_maxcnt);
+               SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+               SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
+               SCVAL(outbuf,smb_vwv0,0xFF);
+               set_message(outbuf,12,smb_maxcnt,False);
+               header.data = outbuf;
+               header.length = data - outbuf;
+               header.free = NULL;
+
+               if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
+                       /*
+                        * Special hack for broken Linux with no 64 bit clean sendfile. If we
+                        * return ENOSYS then pretend we just got a normal read.
+                        */
+                       if (errno == ENOSYS)
+                               goto normal_read;
+
+                       DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
+                               fsp->fsp_name, strerror(errno) ));
+                       exit_server("send_file_readX sendfile failed");
+               }
+
+               DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
+                       fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+               return -1;
+       }
+
+  normal_read:
+
+#endif
+
+       nread = read_file(fsp,data,startpos,smb_maxcnt);
+  
+       if (nread < 0) {
+               END_PROFILE(SMBreadX);
+               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, ( "send_file_readX fnum=%d max=%d nread=%d\n",
+               fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+
+       return nread;
+}
 
 /****************************************************************************
-  reply to a read and X
+ Reply to a read and X.
 ****************************************************************************/
+
 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
-  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;
-  START_PROFILE(SMBreadX);
-
-  /* If it's an IPC, pass off the pipe handler. */
-  if (IS_IPC(conn)) {
-    END_PROFILE(SMBreadX);
-    return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
-  }
-
-  CHECK_FSP(fsp,conn);
-  CHECK_READ(fsp);
-
-  set_message(outbuf,12,0,True);
-  data = smb_buf(outbuf);
-
-  if(CVAL(inbuf,smb_wct) == 12) {
+       files_struct *fsp = file_fsp(inbuf,smb_vwv2);
+       SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
+       ssize_t nread = -1;
+       size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
+#if 0
+       size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
+#endif
+
+       START_PROFILE(SMBreadX);
+
+       /* If it's an IPC, pass off the pipe handler. */
+       if (IS_IPC(conn)) {
+               END_PROFILE(SMBreadX);
+               return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
+       }
+
+       CHECK_FSP(fsp,conn);
+       CHECK_READ(fsp);
+
+       set_message(outbuf,12,0,True);
+
+       if(CVAL(inbuf,smb_wct) == 12) {
 #ifdef LARGE_SMB_OFF_T
-    /*
-     * This is a large offset (64 bit) read.
-     */
-    startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
+               /*
+                * This is a large offset (64 bit) read.
+                */
+               startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
 
 #else /* !LARGE_SMB_OFF_T */
 
-    /*
-     * Ensure we haven't been sent a >32 bit offset.
-     */
+               /*
+                * Ensure we haven't been sent a >32 bit offset.
+                */
 
-    if(IVAL(inbuf,smb_vwv10) != 0) {
-      DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
+               if(IVAL(inbuf,smb_vwv10) != 0) {
+                       DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
-      END_PROFILE(SMBreadX);
-      return ERROR_DOS(ERRDOS,ERRbadaccess);
-    }
+                       END_PROFILE(SMBreadX);
+                       return ERROR_DOS(ERRDOS,ERRbadaccess);
+               }
 
 #endif /* LARGE_SMB_OFF_T */
 
-  }
+       }
 
-  if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
-    END_PROFILE(SMBreadX);
-    return ERROR_DOS(ERRDOS,ERRlock);
-  }
-  nread = read_file(fsp,data,startpos,smb_maxcnt);
+       if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+               END_PROFILE(SMBreadX);
+               return ERROR_DOS(ERRDOS,ERRlock);
+       }
 
-  if (nread < 0) {
-    END_PROFILE(SMBreadX);
-    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, ( "readX fnum=%d min=%d max=%d nread=%d\n",
-             fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
+       nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
+       if (nread != -1)
+               nread = chain_reply(inbuf,outbuf,length,bufsize);
 
-  END_PROFILE(SMBreadX);
-  return chain_reply(inbuf,outbuf,length,bufsize);
+       END_PROFILE(SMBreadX);
+       return nread;
 }
 
 /****************************************************************************
-  reply to a writebraw (core+ or LANMAN1.0 protocol)
+ Reply to a writebraw (core+ or LANMAN1.0 protocol).
 ****************************************************************************/
 
 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
@@ -1777,7 +1874,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        CHECK_WRITE(fsp);
   
        tcount = IVAL(inbuf,smb_vwv1);
-       startpos = IVAL(inbuf,smb_vwv3);
+       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
        write_through = BITSETW(inbuf+smb_vwv7,0);
 
        /* We have to deal with slightly different formats depending
@@ -1806,7 +1903,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
                fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
 
-       if (nwritten < numtowrite)  {
+       if (nwritten < (ssize_t)numtowrite)  {
                END_PROFILE(SMBwritebraw);
                return(UNIXERROR(ERRHRD,ERRdiskfull));
        }
@@ -1888,7 +1985,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
 }
 
 /****************************************************************************
-  reply to a writeunlock (core+)
+ Reply to a writeunlock (core+).
 ****************************************************************************/
 
 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
@@ -1907,7 +2004,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
        CHECK_WRITE(fsp);
 
        numtowrite = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL(inbuf,smb_vwv2);
+       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
        data = smb_buf(inbuf) + 3;
   
        if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, 
@@ -1929,7 +2026,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
 
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                END_PROFILE(SMBwriteunlock);
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
+               return(UNIXERROR(ERRHRD,ERRdiskfull));
        }
 
        status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, 
@@ -1950,7 +2047,6 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
        return outsize;
 }
 
-
 /****************************************************************************
  Reply to a write.
 ****************************************************************************/
@@ -1975,7 +2071,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
        CHECK_WRITE(fsp);
 
        numtowrite = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL(inbuf,smb_vwv2);
+       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
        data = smb_buf(inbuf) + 3;
   
        if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
@@ -2011,7 +2107,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
 
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                END_PROFILE(SMBwrite);
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
+               return(UNIXERROR(ERRHRD,ERRdiskfull));
        }
 
        outsize = set_message(outbuf,1,0,True);
@@ -2025,194 +2121,202 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
   
        DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
 
-       END_PROFILE(SMBwrite);
-       return(outsize);
-}
+       END_PROFILE(SMBwrite);
+       return(outsize);
+}
+
+/****************************************************************************
+ Reply to a write and X.
+****************************************************************************/
+
+int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
+{
+       files_struct *fsp = file_fsp(inbuf,smb_vwv2);
+       SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
+       size_t numtowrite = SVAL(inbuf,smb_vwv10);
+       BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
+       ssize_t nwritten = -1;
+       unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
+       unsigned int smblen = smb_len(inbuf);
+       char *data;
+       BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
+       START_PROFILE(SMBwriteX);
+
+       /* If it's an IPC, pass off the pipe handler. */
+       if (IS_IPC(conn)) {
+               END_PROFILE(SMBwriteX);
+               return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
+       }
+
+       CHECK_FSP(fsp,conn);
+       CHECK_WRITE(fsp);
+
+       /* Deal with possible LARGE_WRITEX */
+       if (large_writeX)
+               numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
+
+       if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
+               END_PROFILE(SMBwriteX);
+               return ERROR_DOS(ERRDOS,ERRbadmem);
+       }
 
+       data = smb_base(inbuf) + smb_doff;
 
-/****************************************************************************
-  reply to a write and X
-****************************************************************************/
-int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
-{
-  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);
-  ssize_t nwritten = -1;
-  unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
-  unsigned int smblen = smb_len(inbuf);
-  char *data;
-  BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
-  START_PROFILE(SMBwriteX);
-
-  /* If it's an IPC, pass off the pipe handler. */
-  if (IS_IPC(conn)) {
-    END_PROFILE(SMBwriteX);
-    return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
-  }
-
-  CHECK_FSP(fsp,conn);
-  CHECK_WRITE(fsp);
-
-  /* Deal with possible LARGE_WRITEX */
-  if (large_writeX)
-    numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
-
-  if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
-    END_PROFILE(SMBwriteX);
-    return ERROR_DOS(ERRDOS,ERRbadmem);
-  }
-
-  data = smb_base(inbuf) + smb_doff;
-
-  if(CVAL(inbuf,smb_wct) == 14) {
+       if(CVAL(inbuf,smb_wct) == 14) {
 #ifdef LARGE_SMB_OFF_T
-    /*
-     * This is a large offset (64 bit) write.
-     */
-    startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
+               /*
+                * This is a large offset (64 bit) write.
+                */
+               startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
 
 #else /* !LARGE_SMB_OFF_T */
 
-    /*
-     * Ensure we haven't been sent a >32 bit offset.
-     */
+               /*
+                * Ensure we haven't been sent a >32 bit offset.
+                */
 
-    if(IVAL(inbuf,smb_vwv12) != 0) {
-      DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
+               if(IVAL(inbuf,smb_vwv12) != 0) {
+                       DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
-      END_PROFILE(SMBwriteX);
-      return ERROR_DOS(ERRDOS,ERRbadaccess);
-    }
+                       END_PROFILE(SMBwriteX);
+                       return ERROR_DOS(ERRDOS,ERRbadaccess);
+               }
 
 #endif /* LARGE_SMB_OFF_T */
-  }
-
-  if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
-    END_PROFILE(SMBwriteX);
-    return ERROR_DOS(ERRDOS,ERRlock);
-  }
-
-  /* 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(numtowrite == 0)
-    nwritten = 0;
-  else
-    nwritten = write_file(fsp,data,startpos,numtowrite);
+       }
+
+       if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
+               END_PROFILE(SMBwriteX);
+               return ERROR_DOS(ERRDOS,ERRlock);
+       }
+
+       /* 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(numtowrite == 0)
+               nwritten = 0;
+       else
+               nwritten = write_file(fsp,data,startpos,numtowrite);
   
-  if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
-    END_PROFILE(SMBwriteX);
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
+       if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
+               END_PROFILE(SMBwriteX);
+               return(UNIXERROR(ERRHRD,ERRdiskfull));
+       }
 
-  set_message(outbuf,6,0,True);
+       set_message(outbuf,6,0,True);
   
-  SSVAL(outbuf,smb_vwv2,nwritten);
-  if (large_writeX)
-    SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
+       SSVAL(outbuf,smb_vwv2,nwritten);
+       if (large_writeX)
+               SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
 
-  if (nwritten < (ssize_t)numtowrite) {
-    SCVAL(outbuf,smb_rcls,ERRHRD);
-    SSVAL(outbuf,smb_err,ERRdiskfull);      
-  }
+       if (nwritten < (ssize_t)numtowrite) {
+               SCVAL(outbuf,smb_rcls,ERRHRD);
+               SSVAL(outbuf,smb_err,ERRdiskfull);      
+       }
 
-  DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
-          fsp->fnum, (int)numtowrite, (int)nwritten));
+       DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
+               fsp->fnum, (int)numtowrite, (int)nwritten));
 
-  if (lp_syncalways(SNUM(conn)) || write_through)
-    sync_file(conn,fsp);
+       if (lp_syncalways(SNUM(conn)) || write_through)
+               sync_file(conn,fsp);
 
-  END_PROFILE(SMBwriteX);
-  return chain_reply(inbuf,outbuf,length,bufsize);
+       END_PROFILE(SMBwriteX);
+       return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
-
 /****************************************************************************
-  reply to a lseek
+ Reply to a lseek.
 ****************************************************************************/
 
 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
 {
-  SMB_OFF_T startpos;
-  SMB_OFF_T res= -1;
-  int mode,umode;
-  int outsize = 0;
-  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
-  START_PROFILE(SMBlseek);
+       SMB_OFF_T startpos;
+       SMB_OFF_T res= -1;
+       int mode,umode;
+       int outsize = 0;
+       files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+       START_PROFILE(SMBlseek);
 
-  CHECK_FSP(fsp,conn);
+       CHECK_FSP(fsp,conn);
 
-  flush_write_cache(fsp, SEEK_FLUSH);
+       flush_write_cache(fsp, SEEK_FLUSH);
 
-  mode = SVAL(inbuf,smb_vwv1) & 3;
-  startpos = IVALS(inbuf,smb_vwv2);
+       mode = SVAL(inbuf,smb_vwv1) & 3;
+       /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
+       startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
 
-  switch (mode) {
-    case 0: umode = SEEK_SET; break;
-    case 1: umode = SEEK_CUR; break;
-    case 2: umode = SEEK_END; break;
-    default:
-      umode = SEEK_SET; break;
-  }
+       switch (mode) {
+               case 0:
+                       umode = SEEK_SET;
+                       break;
+               case 1:
+                       umode = SEEK_CUR;
+                       break;
+               case 2:
+                       umode = SEEK_END;
+                       break;
+               default:
+                       umode = SEEK_SET;
+                       break;
+       }
 
-  if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
-    /*
-     * Check for the special case where a seek before the start
-     * of the file sets the offset to zero. Added in the CIFS spec,
-     * section 4.2.7.
-     */
+       if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
+               /*
+                * Check for the special case where a seek before the start
+                * of the file sets the offset to zero. Added in the CIFS spec,
+                * section 4.2.7.
+                */
 
-    if(errno == EINVAL) {
-      SMB_OFF_T current_pos = startpos;
+               if(errno == EINVAL) {
+                       SMB_OFF_T current_pos = startpos;
 
-      if(umode == SEEK_CUR) {
+                       if(umode == SEEK_CUR) {
 
-        if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
-                       END_PROFILE(SMBlseek);
-          return(UNIXERROR(ERRDOS,ERRnoaccess));
-       }
+                               if((current_pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
+                                       END_PROFILE(SMBlseek);
+                                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+                               }
 
-        current_pos += startpos;
+                               current_pos += startpos;
 
-      } else if (umode == SEEK_END) {
+                       } else if (umode == SEEK_END) {
 
-        SMB_STRUCT_STAT sbuf;
+                               SMB_STRUCT_STAT sbuf;
 
-        if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
-                 END_PROFILE(SMBlseek);
-          return(UNIXERROR(ERRDOS,ERRnoaccess));
-       }
+                               if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
+                                       END_PROFILE(SMBlseek);
+                                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+                               }
 
-        current_pos += sbuf.st_size;
-      }
+                               current_pos += sbuf.st_size;
+                       }
  
-      if(current_pos < 0)
-        res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
-    }
+                       if(current_pos < 0)
+                               res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
+               }
 
-    if(res == -1) {
-      END_PROFILE(SMBlseek);
-      return(UNIXERROR(ERRDOS,ERRnoaccess));
-    }
-  }
+               if(res == -1) {
+                       END_PROFILE(SMBlseek);
+                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+               }
+       }
 
-  fsp->pos = res;
+       fsp->pos = res;
   
-  outsize = set_message(outbuf,2,0,True);
-  SIVAL(outbuf,smb_vwv0,res);
+       outsize = set_message(outbuf,2,0,True);
+       SIVAL(outbuf,smb_vwv0,res);
   
-  DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
-          fsp->fnum, (double)startpos, (double)res, mode));
+       DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
+               fsp->fnum, (double)startpos, (double)res, mode));
 
-  END_PROFILE(SMBlseek);
-  return(outsize);
+       END_PROFILE(SMBlseek);
+       return(outsize);
 }
 
 /****************************************************************************
-  reply to a flush
+ Reply to a flush.
 ****************************************************************************/
 
 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
@@ -2234,10 +2338,10 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a exit
+ Reply to a exit.
 ****************************************************************************/
+
 int reply_exit(connection_struct *conn, 
               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2251,13 +2355,14 @@ int reply_exit(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
  Reply to a close - has to deal with closing a directory opened by NT SMB's.
 ****************************************************************************/
+
 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
                 int dum_buffsize)
 {
+       extern struct current_user current_user;
        int outsize = 0;
        time_t mtime;
        int32 eclass = 0, err = 0;
@@ -2278,7 +2383,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
         * We can only use CHECK_FSP if we know it's not a directory.
         */
 
-       if(!fsp || (fsp->conn != conn)) {
+       if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
                END_PROFILE(SMBclose);
                return ERROR_DOS(ERRDOS,ERRbadfid);
        }
@@ -2336,9 +2441,8 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a writeclose (Core+ protocol)
+ Reply to a writeclose (Core+ protocol).
 ****************************************************************************/
 
 int reply_writeclose(connection_struct *conn,
@@ -2358,7 +2462,7 @@ int reply_writeclose(connection_struct *conn,
        CHECK_WRITE(fsp);
 
        numtowrite = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL(inbuf,smb_vwv2);
+       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
        mtime = make_unix_date3(inbuf+smb_vwv4);
        data = smb_buf(inbuf) + 1;
   
@@ -2377,9 +2481,9 @@ int reply_writeclose(connection_struct *conn,
                 fsp->fnum, (int)numtowrite, (int)nwritten,
                 conn->num_files_open));
   
-       if (nwritten <= 0) {
+       if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                END_PROFILE(SMBwriteclose);
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
+               return(UNIXERROR(ERRHRD,ERRdiskfull));
        }
  
        if(close_err != 0) {
@@ -2395,10 +2499,10 @@ int reply_writeclose(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a lock
+ Reply to a lock.
 ****************************************************************************/
+
 int reply_lock(connection_struct *conn,
               char *inbuf,char *outbuf, int length, int dum_buffsize)
 {
@@ -2420,13 +2524,13 @@ int reply_lock(connection_struct *conn,
 
        status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
        if (NT_STATUS_V(status)) {
-               if (lp_blocking_locks(SNUM(conn))) {
+               if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
                        /*
                         * 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)) {
+                       if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
                                END_PROFILE(SMBlock);
                                return -1;
                        }
@@ -2439,10 +2543,10 @@ int reply_lock(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a unlock
+ Reply to a unlock.
 ****************************************************************************/
+
 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
                 int dum_buffsize)
 {
@@ -2470,10 +2574,10 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a tdis
+ Reply to a tdis.
 ****************************************************************************/
+
 int reply_tdis(connection_struct *conn, 
               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2497,11 +2601,10 @@ int reply_tdis(connection_struct *conn,
        return outsize;
 }
 
-
-
 /****************************************************************************
-  reply to a echo
+ Reply to a echo.
 ****************************************************************************/
+
 int reply_echo(connection_struct *conn,
               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2539,10 +2642,10 @@ int reply_echo(connection_struct *conn,
        return -1;
 }
 
-
 /****************************************************************************
-  reply to a printopen
+ Reply to a printopen.
 ****************************************************************************/
+
 int reply_printopen(connection_struct *conn, 
                    char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2573,10 +2676,10 @@ int reply_printopen(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a printclose
+ Reply to a printclose.
 ****************************************************************************/
+
 int reply_printclose(connection_struct *conn,
                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2607,10 +2710,10 @@ int reply_printclose(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a printqueue
+ Reply to a printqueue.
 ****************************************************************************/
+
 int reply_printqueue(connection_struct *conn,
                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2678,45 +2781,46 @@ int reply_printqueue(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a printwrite
+ Reply to a printwrite.
 ****************************************************************************/
+
 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int numtowrite;
-  int outsize = set_message(outbuf,0,0,True);
-  char *data;
-  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
-  START_PROFILE(SMBsplwr);
+       int numtowrite;
+       int outsize = set_message(outbuf,0,0,True);
+       char *data;
+       files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+
+       START_PROFILE(SMBsplwr);
   
-  if (!CAN_PRINT(conn)) {
-    END_PROFILE(SMBsplwr);
-    return ERROR_DOS(ERRDOS,ERRnoaccess);
-  }
+       if (!CAN_PRINT(conn)) {
+               END_PROFILE(SMBsplwr);
+               return ERROR_DOS(ERRDOS,ERRnoaccess);
+       }
 
-  CHECK_FSP(fsp,conn);
-  CHECK_WRITE(fsp);
+       CHECK_FSP(fsp,conn);
+       CHECK_WRITE(fsp);
 
-  numtowrite = SVAL(smb_buf(inbuf),1);
-  data = smb_buf(inbuf) + 3;
+       numtowrite = SVAL(smb_buf(inbuf),1);
+       data = smb_buf(inbuf) + 3;
   
-  if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
-    END_PROFILE(SMBsplwr);
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
+       if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
+               END_PROFILE(SMBsplwr);
+               return(UNIXERROR(ERRHRD,ERRdiskfull));
+       }
 
-  DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
+       DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
   
-  END_PROFILE(SMBsplwr);
-  return(outsize);
+       END_PROFILE(SMBsplwr);
+       return(outsize);
 }
 
-
 /****************************************************************************
  The guts of the mkdir command, split out so it may be called by the NT SMB
  code. 
 ****************************************************************************/
+
 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
 {
        BOOL bad_path = False;
@@ -2726,7 +2830,7 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
        unix_convert(directory,conn,0,&bad_path,&sbuf);
        
        if (check_name(directory, conn))
-               ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
+               ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
        
        if (ret == -1) {
                NTSTATUS nterr = set_bad_path_error(errno, bad_path);
@@ -2772,7 +2876,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 
 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
 {
-       char *dname = NULL;
+       const char *dname = NULL;
        BOOL ret = False;
        void *dirptr = OpenDir(conn, directory, False);
 
@@ -2797,7 +2901,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
                pstrcat(fullname, "/");
                pstrcat(fullname, dname);
 
-               if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
+               if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
                        ret = True;
                        break;
                }
@@ -2807,11 +2911,11 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
                                ret = True;
                                break;
                        }
-                       if(vfs_rmdir(conn,fullname) != 0) {
+                       if(SMB_VFS_RMDIR(conn,fullname) != 0) {
                                ret = True;
                                break;
                        }
-               } else if(vfs_unlink(conn,fullname) != 0) {
+               } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
                        ret = True;
                        break;
                }
@@ -2828,7 +2932,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
 {
        BOOL ok;
 
-       ok = (vfs_rmdir(conn,directory) == 0);
+       ok = (SMB_VFS_RMDIR(conn,directory) == 0);
        if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
                /* 
                 * Check to see if the only thing in this directory are
@@ -2837,7 +2941,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
                 * do a recursive delete) then fail the rmdir.
                 */
                BOOL all_veto_files = True;
-               char *dname;
+               const char *dname;
                void *dirptr = OpenDir(conn, directory, False);
 
                if(dirptr != NULL) {
@@ -2870,21 +2974,21 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
                                        pstrcat(fullname, "/");
                                        pstrcat(fullname, dname);
                      
-                                       if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
+                                       if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
                                                break;
                                        if(st.st_mode & S_IFDIR) {
                                                if(lp_recursive_veto_delete(SNUM(conn))) {
                                                        if(recursive_rmdir(conn, fullname) != 0)
                                                                break;
                                                }
-                                               if(vfs_rmdir(conn,fullname) != 0)
+                                               if(SMB_VFS_RMDIR(conn,fullname) != 0)
                                                        break;
-                                       } else if(vfs_unlink(conn,fullname) != 0)
+                                       } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
                                                break;
                                }
                                CloseDir(dirptr);
                                /* Retry the rmdir */
-                               ok = (vfs_rmdir(conn,directory) == 0);
+                               ok = (SMB_VFS_RMDIR(conn,directory) == 0);
                        } else {
                                CloseDir(dirptr);
                        }
@@ -2905,103 +3009,108 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
 
 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  pstring directory;
-  int outsize = 0;
-  BOOL ok = False;
-  BOOL bad_path = False;
-  SMB_STRUCT_STAT sbuf;
-  START_PROFILE(SMBrmdir);
+       pstring directory;
+       int outsize = 0;
+       BOOL ok = False;
+       BOOL bad_path = False;
+       SMB_STRUCT_STAT sbuf;
+       START_PROFILE(SMBrmdir);
 
-  srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
+       srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
 
-  RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
+       RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
 
-  unix_convert(directory,conn, NULL,&bad_path,&sbuf);
+       unix_convert(directory,conn, NULL,&bad_path,&sbuf);
   
-  if (check_name(directory,conn))
-  {
-    dptr_closepath(directory,SVAL(inbuf,smb_pid));
-    ok = rmdir_internals(conn, directory);
-  }
+       if (check_name(directory,conn)) {
+               dptr_closepath(directory,SVAL(inbuf,smb_pid));
+               ok = rmdir_internals(conn, directory);
+       }
   
-  if (!ok)
-  {
-    set_bad_path_error(errno, bad_path);
-    END_PROFILE(SMBrmdir);
-    return(UNIXERROR(ERRDOS,ERRbadpath));
-  }
+       if (!ok) {
+               set_bad_path_error(errno, bad_path);
+               END_PROFILE(SMBrmdir);
+               return(UNIXERROR(ERRDOS,ERRbadpath));
+       }
  
-  outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,True);
   
-  DEBUG( 3, ( "rmdir %s\n", directory ) );
+       DEBUG( 3, ( "rmdir %s\n", directory ) );
   
-  END_PROFILE(SMBrmdir);
-  return(outsize);
+       END_PROFILE(SMBrmdir);
+       return(outsize);
 }
 
-
 /*******************************************************************
-resolve wildcards in a filename rename
+ Resolve wildcards in a filename rename.
 ********************************************************************/
-static BOOL resolve_wildcards(char *name1,char *name2)
+
+static BOOL resolve_wildcards(const char *name1, char *name2)
 {
-  fstring root1,root2;
-  fstring ext1,ext2;
-  char *p,*p2;
+       fstring root1,root2;
+       fstring ext1,ext2;
+       char *p,*p2, *pname1, *pname2;
+       int available_space;
+       
 
-  name1 = strrchr_m(name1,'/');
-  name2 = strrchr_m(name2,'/');
+       pname1 = strrchr_m(name1,'/');
+       pname2 = strrchr_m(name2,'/');
 
-  if (!name1 || !name2) return(False);
+       if (!pname1 || !pname2)
+               return(False);
   
-  fstrcpy(root1,name1);
-  fstrcpy(root2,name2);
-  p = strrchr_m(root1,'.');
-  if (p) {
-    *p = 0;
-    fstrcpy(ext1,p+1);
-  } else {
-    fstrcpy(ext1,"");    
-  }
-  p = strrchr_m(root2,'.');
-  if (p) {
-    *p = 0;
-    fstrcpy(ext2,p+1);
-  } else {
-    fstrcpy(ext2,"");    
-  }
-
-  p = root1;
-  p2 = root2;
-  while (*p2) {
-    if (*p2 == '?') {
-      *p2 = *p;
-      p2++;
-    } else {
-      p2++;
-    }
-    if (*p) p++;
-  }
-
-  p = ext1;
-  p2 = ext2;
-  while (*p2) {
-    if (*p2 == '?') {
-      *p2 = *p;
-      p2++;
-    } else {
-      p2++;
-    }
-    if (*p) p++;
-  }
-
-  pstrcpy(name2,root2);
-  if (ext2[0]) {
-    pstrcat(name2,".");
-    pstrcat(name2,ext2);
-  }
-
-  return(True);
+       fstrcpy(root1,pname1);
+       fstrcpy(root2,pname2);
+       p = strrchr_m(root1,'.');
+       if (p) {
+               *p = 0;
+               fstrcpy(ext1,p+1);
+       } else {
+               fstrcpy(ext1,"");    
+       }
+       p = strrchr_m(root2,'.');
+       if (p) {
+               *p = 0;
+               fstrcpy(ext2,p+1);
+       } else {
+               fstrcpy(ext2,"");    
+       }
+
+       p = root1;
+       p2 = root2;
+       while (*p2) {
+               if (*p2 == '?') {
+                       *p2 = *p;
+                       p2++;
+               } else {
+                       p2++;
+               }
+               if (*p)
+                       p++;
+       }
+
+       p = ext1;
+       p2 = ext2;
+       while (*p2) {
+               if (*p2 == '?') {
+                       *p2 = *p;
+                       p2++;
+               } else {
+                       p2++;
+               }
+               if (*p)
+                       p++;
+       }
+
+       available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
+       
+       if (ext2[0]) {
+               snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
+       } else {
+               pstrcpy_base(pname2, root2, name2);
+       }
+
+       return(True);
 }
 
 /****************************************************************************
@@ -3175,7 +3284,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
                        return NT_STATUS_OBJECT_NAME_COLLISION;
                }
 
-               if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
+               if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
                        DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
                                directory,newname));
                        return NT_STATUS_OK;    
@@ -3195,7 +3304,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
                 * Wildcards - process each file that matches.
                 */
                void *dirptr = NULL;
-               char *dname;
+               const char *dname;
                pstring destname;
                
                if (check_name(directory,conn))
@@ -3242,7 +3351,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
                                        continue;
                                }
                                
-                               if (!conn->vfs_ops.rename(conn,fname,destname))
+                               if (!SMB_VFS_RENAME(conn,fname,destname))
                                        count++;
                                DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
                        }
@@ -3336,7 +3445,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
        if (!target_is_directory && count)
                ofun = FILE_EXISTS_OPEN;
 
-       if (vfs_stat(conn,dest,&sbuf2) == -1)
+       if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
                ZERO_STRUCTP(&sbuf2);
 
        fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
@@ -3348,7 +3457,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
        }
 
        if ((ofun&3) == 1) {
-               if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
+               if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
                        DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
                        /*
                         * Stop the copy from occurring.
@@ -3378,209 +3487,213 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
 }
 
 /****************************************************************************
-  reply to a file copy.
-  ****************************************************************************/
+ Reply to a file copy.
+****************************************************************************/
+
 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int outsize = 0;
-  pstring name;
-  pstring directory;
-  pstring mask,newname;
-  char *p;
-  int count=0;
-  int error = ERRnoaccess;
-  int err = 0;
-  BOOL has_wild;
-  BOOL exists=False;
-  int tid2 = SVAL(inbuf,smb_vwv0);
-  int ofun = SVAL(inbuf,smb_vwv1);
-  int flags = SVAL(inbuf,smb_vwv2);
-  BOOL target_is_directory=False;
-  BOOL bad_path1 = False;
-  BOOL bad_path2 = False;
-  BOOL rc = True;
-  SMB_STRUCT_STAT sbuf1, sbuf2;
-  START_PROFILE(SMBcopy);
-
-  *directory = *mask = 0;
-
-  p = smb_buf(inbuf);
-  p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
-  p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
+       int outsize = 0;
+       pstring name;
+       pstring directory;
+       pstring mask,newname;
+       char *p;
+       int count=0;
+       int error = ERRnoaccess;
+       int err = 0;
+       BOOL has_wild;
+       BOOL exists=False;
+       int tid2 = SVAL(inbuf,smb_vwv0);
+       int ofun = SVAL(inbuf,smb_vwv1);
+       int flags = SVAL(inbuf,smb_vwv2);
+       BOOL target_is_directory=False;
+       BOOL bad_path1 = False;
+       BOOL bad_path2 = False;
+       BOOL rc = True;
+       SMB_STRUCT_STAT sbuf1, sbuf2;
+
+       START_PROFILE(SMBcopy);
+
+       *directory = *mask = 0;
+
+       p = smb_buf(inbuf);
+       p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
+       p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
    
-  DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
+       DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
    
-  if (tid2 != conn->cnum) {
-    /* can't currently handle inter share copies XXXX */
-    DEBUG(3,("Rejecting inter-share copy\n"));
-    END_PROFILE(SMBcopy);
-    return ERROR_DOS(ERRSRV,ERRinvdevice);
-  }
-
-  RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
-  RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
-
-  rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
-  unix_convert(newname,conn,0,&bad_path2,&sbuf2);
-
-  target_is_directory = VALID_STAT_OF_DIR(sbuf2);
-
-  if ((flags&1) && target_is_directory) {
-    END_PROFILE(SMBcopy);
-    return ERROR_DOS(ERRDOS,ERRbadfile);
-  }
-
-  if ((flags&2) && !target_is_directory) {
-    END_PROFILE(SMBcopy);
-    return ERROR_DOS(ERRDOS,ERRbadpath);
-  }
-
-  if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
-    /* wants a tree copy! XXXX */
-    DEBUG(3,("Rejecting tree copy\n"));
-    END_PROFILE(SMBcopy);
-    return ERROR_DOS(ERRSRV,ERRerror);
-  }
-
-  p = strrchr_m(name,'/');
-  if (!p) {
-    pstrcpy(directory,"./");
-    pstrcpy(mask,name);
-  } else {
-    *p = 0;
-    pstrcpy(directory,name);
-    pstrcpy(mask,p+1);
-  }
-
-  /*
-   * We should only check the mangled cache
-   * here if unix_convert failed. This means
-   * that the path in 'mask' doesn't exist
-   * on the file system and so we need to look
-   * for a possible mangle. This patch from
-   * Tine Smukavec <valentin.smukavec@hermes.si>.
-   */
-
-  if (!rc && mangle_is_mangled(mask))
-         mangle_check_cache( mask );
-
-  has_wild = ms_has_wild(mask);
-
-  if (!has_wild) {
-    pstrcat(directory,"/");
-    pstrcat(directory,mask);
-    if (resolve_wildcards(directory,newname) && 
-       copy_file(directory,newname,conn,ofun,
-                 count,target_is_directory,&err)) count++;
-    if(!count && err) {
-               errno = err;
+       if (tid2 != conn->cnum) {
+               /* can't currently handle inter share copies XXXX */
+               DEBUG(3,("Rejecting inter-share copy\n"));
                END_PROFILE(SMBcopy);
-               return(UNIXERROR(ERRHRD,ERRgeneral));
+               return ERROR_DOS(ERRSRV,ERRinvdevice);
        }
-    if (!count) exists = vfs_file_exist(conn,directory,NULL);
-  } else {
-    void *dirptr = NULL;
-    char *dname;
-    pstring destname;
 
-    if (check_name(directory,conn))
-      dirptr = OpenDir(conn, directory, True);
+       RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
 
-    if (dirptr) {
-       error = ERRbadfile;
+       rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
+       unix_convert(newname,conn,0,&bad_path2,&sbuf2);
 
-       if (strequal(mask,"????????.???"))
-         pstrcpy(mask,"*");
+       target_is_directory = VALID_STAT_OF_DIR(sbuf2);
 
-       while ((dname = ReadDirName(dirptr))) {
-           pstring fname;
-           pstrcpy(fname,dname);
-           
-           if(!mask_match(fname, mask, case_sensitive))
-                       continue;
+       if ((flags&1) && target_is_directory) {
+               END_PROFILE(SMBcopy);
+               return ERROR_DOS(ERRDOS,ERRbadfile);
+       }
 
-           error = ERRnoaccess;
-           slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
-           pstrcpy(destname,newname);
-           if (resolve_wildcards(fname,destname) && 
-               copy_file(fname,destname,conn,ofun,
-                         count,target_is_directory,&err)) count++;
-           DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
-         }
-       CloseDir(dirptr);
-    }
-  }
+       if ((flags&2) && !target_is_directory) {
+               END_PROFILE(SMBcopy);
+               return ERROR_DOS(ERRDOS,ERRbadpath);
+       }
+
+       if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
+               /* wants a tree copy! XXXX */
+               DEBUG(3,("Rejecting tree copy\n"));
+               END_PROFILE(SMBcopy);
+               return ERROR_DOS(ERRSRV,ERRerror);
+       }
+
+       p = strrchr_m(name,'/');
+       if (!p) {
+               pstrcpy(directory,"./");
+               pstrcpy(mask,name);
+       } else {
+               *p = 0;
+               pstrcpy(directory,name);
+               pstrcpy(mask,p+1);
+       }
+
+       /*
+        * We should only check the mangled cache
+        * here if unix_convert failed. This means
+        * that the path in 'mask' doesn't exist
+        * on the file system and so we need to look
+        * for a possible mangle. This patch from
+        * Tine Smukavec <valentin.smukavec@hermes.si>.
+        */
+
+       if (!rc && mangle_is_mangled(mask))
+               mangle_check_cache( mask );
+
+       has_wild = ms_has_wild(mask);
+
+       if (!has_wild) {
+               pstrcat(directory,"/");
+               pstrcat(directory,mask);
+               if (resolve_wildcards(directory,newname) &&
+                               copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
+                       count++;
+               if(!count && err) {
+                       errno = err;
+                       END_PROFILE(SMBcopy);
+                       return(UNIXERROR(ERRHRD,ERRgeneral));
+               }
+               if (!count) {
+                       exists = vfs_file_exist(conn,directory,NULL);
+               }
+       } else {
+               void *dirptr = NULL;
+               const 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))
+                                       continue;
+
+                               error = ERRnoaccess;
+                               slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+                               pstrcpy(destname,newname);
+                               if (resolve_wildcards(fname,destname) && 
+                                               copy_file(fname,destname,conn,ofun,
+                                               count,target_is_directory,&err))
+                                       count++;
+                               DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
+                       }
+                       CloseDir(dirptr);
+               }
+       }
   
-  if (count == 0) {
-    if(err) {
-      /* Error on close... */
-      errno = err;
-      END_PROFILE(SMBcopy);
-      return(UNIXERROR(ERRHRD,ERRgeneral));
-    }
-
-    if (exists) {
-      END_PROFILE(SMBcopy);
-      return ERROR_DOS(ERRDOS,error);
-    } else
-    {
-      if((errno == ENOENT) && (bad_path1 || bad_path2))
-      {
-        unix_ERR_class = ERRDOS;
-        unix_ERR_code = ERRbadpath;
-      }
-      END_PROFILE(SMBcopy);
-      return(UNIXERROR(ERRDOS,error));
-    }
-  }
+       if (count == 0) {
+               if(err) {
+                       /* Error on close... */
+                       errno = err;
+                       END_PROFILE(SMBcopy);
+                       return(UNIXERROR(ERRHRD,ERRgeneral));
+               }
+
+               if (exists) {
+                       END_PROFILE(SMBcopy);
+                       return ERROR_DOS(ERRDOS,error);
+               } else {
+                       if((errno == ENOENT) && (bad_path1 || bad_path2)) {
+                               unix_ERR_class = ERRDOS;
+                               unix_ERR_code = ERRbadpath;
+                       }
+                       END_PROFILE(SMBcopy);
+                       return(UNIXERROR(ERRDOS,error));
+               }
+       }
   
-  outsize = set_message(outbuf,1,0,True);
-  SSVAL(outbuf,smb_vwv0,count);
+       outsize = set_message(outbuf,1,0,True);
+       SSVAL(outbuf,smb_vwv0,count);
 
-  END_PROFILE(SMBcopy);
-  return(outsize);
+       END_PROFILE(SMBcopy);
+       return(outsize);
 }
 
 /****************************************************************************
-  reply to a setdir
+ Reply to a setdir.
 ****************************************************************************/
+
 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int snum;
-  int outsize = 0;
-  BOOL ok = False;
-  pstring newdir;
-  START_PROFILE(pathworks_setdir);
+       int snum;
+       int outsize = 0;
+       BOOL ok = False;
+       pstring newdir;
+
+       START_PROFILE(pathworks_setdir);
   
-  snum = SNUM(conn);
-  if (!CAN_SETDIR(snum)) {
-    END_PROFILE(pathworks_setdir);
-    return ERROR_DOS(ERRDOS,ERRnoaccess);
-  }
+       snum = SNUM(conn);
+       if (!CAN_SETDIR(snum)) {
+               END_PROFILE(pathworks_setdir);
+               return ERROR_DOS(ERRDOS,ERRnoaccess);
+       }
 
-  srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
+       srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
   
-  if (strlen(newdir) == 0) {
-         ok = True;
-  } else {
-         ok = vfs_directory_exist(conn,newdir,NULL);
-         if (ok) {
-                 string_set(&conn->connectpath,newdir);
-         }
-  }
+       if (strlen(newdir) == 0) {
+               ok = True;
+       } else {
+               ok = vfs_directory_exist(conn,newdir,NULL);
+               if (ok)
+                       string_set(&conn->connectpath,newdir);
+       }
   
-  if (!ok) {
-         END_PROFILE(pathworks_setdir);
-         return ERROR_DOS(ERRDOS,ERRbadpath);
-  }
+       if (!ok) {
+               END_PROFILE(pathworks_setdir);
+               return ERROR_DOS(ERRDOS,ERRbadpath);
+       }
   
-  outsize = set_message(outbuf,0,0,True);
-  SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
+       outsize = set_message(outbuf,0,0,True);
+       SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
   
-  DEBUG(3,("setdir %s\n", newdir));
+       DEBUG(3,("setdir %s\n", newdir));
 
-  END_PROFILE(pathworks_setdir);
-  return(outsize);
+       END_PROFILE(pathworks_setdir);
+       return(outsize);
 }
 
 /****************************************************************************
@@ -3601,42 +3714,43 @@ uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
 
 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
 {
-  SMB_BIG_UINT count = 0;
+       SMB_BIG_UINT count = 0;
 
-  if(!large_file_format) {
-    count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
-  } else {
+       if(!large_file_format) {
+               count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
+       } else {
 
 #if defined(HAVE_LONGLONG)
-    count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
-            ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
+               count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
+                       ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
 #else /* HAVE_LONGLONG */
 
-    /*
-     * NT4.x seems to be broken in that it sends large file (64 bit)
-     * lockingX calls even if the CAP_LARGE_FILES was *not*
-     * negotiated. For boxes without large unsigned ints truncate the
-     * lock count by dropping the top 32 bits.
-     */
-
-    if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
-      DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
-            (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
-            (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
-      SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
-    }
-
-    count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
+               /*
+                * NT4.x seems to be broken in that it sends large file (64 bit)
+                * lockingX calls even if the CAP_LARGE_FILES was *not*
+                * negotiated. For boxes without large unsigned ints truncate the
+                * lock count by dropping the top 32 bits.
+                */
+
+               if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
+                       DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
+                               (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
+                               (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
+                               SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
+               }
+
+               count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
 #endif /* HAVE_LONGLONG */
-  }
+       }
 
-  return count;
+       return count;
 }
 
 #if !defined(HAVE_LONGLONG)
 /****************************************************************************
  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
 ****************************************************************************/
+
 static uint32 map_lock_offset(uint32 high, uint32 low)
 {
        unsigned int i;
@@ -3672,51 +3786,51 @@ static uint32 map_lock_offset(uint32 high, uint32 low)
 
 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
 {
-  SMB_BIG_UINT offset = 0;
+       SMB_BIG_UINT offset = 0;
 
-  *err = False;
+       *err = False;
 
-  if(!large_file_format) {
-    offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
-  } else {
+       if(!large_file_format) {
+               offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
+       } else {
 
 #if defined(HAVE_LONGLONG)
-    offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
-            ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
+               offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
+                               ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
 #else /* HAVE_LONGLONG */
 
-    /*
-     * NT4.x seems to be broken in that it sends large file (64 bit)
-     * lockingX calls even if the CAP_LARGE_FILES was *not*
-     * negotiated. For boxes without large unsigned ints mangle the
-     * lock offset by mapping the top 32 bits onto the lower 32.
-     */
+               /*
+                * NT4.x seems to be broken in that it sends large file (64 bit)
+                * lockingX calls even if the CAP_LARGE_FILES was *not*
+                * negotiated. For boxes without large unsigned ints mangle the
+                * lock offset by mapping the top 32 bits onto the lower 32.
+                */
       
-    if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
-      uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
-      uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
-      uint32 new_low = 0;
-
-      if((new_low = map_lock_offset(high, low)) == 0) {
-        *err = True;
-        return (SMB_BIG_UINT)-1;
-      }
-
-      DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
-            (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
-      SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
-      SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
-    }
-
-    offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
+               if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
+                       uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
+                       uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
+                       uint32 new_low = 0;
+
+                       if((new_low = map_lock_offset(high, low)) == 0) {
+                               *err = True;
+                               return (SMB_BIG_UINT)-1;
+                       }
+
+                       DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
+                               (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
+                       SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
+                       SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
+               }
+
+               offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
 #endif /* HAVE_LONGLONG */
-  }
+       }
 
-  return offset;
+       return offset;
 }
 
 /****************************************************************************
-  reply to a lockingX request
+ Reply to a lockingX request.
 ****************************************************************************/
 
 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
@@ -3855,13 +3969,13 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
                                 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
                if (NT_STATUS_V(status)) {
-                       if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
+                       if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
                                /*
                                 * 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)) {
+                               if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
                                        END_PROFILE(SMBlockingX);
                                        return -1;
                                }
@@ -3935,7 +4049,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
        CHECK_FSP(fsp,conn);
        CHECK_READ(fsp);
 
-       startpos = IVAL(inbuf,smb_vwv1);
+       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
        maxcount = SVAL(inbuf,smb_vwv3);
 
        data = smb_buf(outbuf);
@@ -4063,7 +4177,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
        CHECK_ERROR(fsp);
 
        tcount = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL(inbuf,smb_vwv3);
+       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
        write_through = BITSETW(inbuf+smb_vwv7,0);
        numtowrite = SVAL(inbuf,smb_vwv10);
        smb_doff = SVAL(inbuf,smb_vwv11);
@@ -4163,7 +4277,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
        CHECK_WRITE(fsp);
 
        tcount = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL(inbuf,smb_vwv2);
+       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
        numtowrite = SVAL(inbuf,smb_vwv6);
        smb_doff = SVAL(inbuf,smb_vwv7);