Optimization on POSIX platforms that have fstatat.
[obnox/samba/samba-obnox.git] / source3 / modules / vfs_default.c
index 3691fb0e7e77c82ae5814c109088a9e70f37e2bd..82d059c28fae90afe03c6b0e84ebfcf438bb511e 100644 (file)
 */
 
 #include "includes.h"
+#include "system/time.h"
+#include "system/filesys.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "ntioctl.h"
+#include "smbprofile.h"
+#include "../libcli/security/security.h"
+#include "passdb/lookup_sid.h"
+#include "source3/include/msdfs.h"
+#include "librpc/gen_ndr/ndr_dfsblobs.h"
+#include "lib/util/tevent_unix.h"
+#include "lib/asys/asys.h"
+#include "lib/util/tevent_ntstatus.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
@@ -29,7 +42,7 @@
    is sure to try and execute them.  These stubs are used to prevent
    this possibility. */
 
-static int vfswrap_connect(vfs_handle_struct *handle,  const char *service, const char *user)
+static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
 {
     return 0;    /* Return >= 0 for success */
 }
@@ -40,7 +53,7 @@ static void vfswrap_disconnect(vfs_handle_struct *handle)
 
 /* Disk operations */
 
-static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,  const char *path, bool small_query, uint64_t *bsize,
+static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path, bool small_query, uint64_t *bsize,
                               uint64_t *dfree, uint64_t *dsize)
 {
        uint64_t result;
@@ -49,7 +62,7 @@ static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,  const char *path,
        return result;
 }
 
-static int vfswrap_get_quota(struct vfs_handle_struct *handle,  enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
+static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
 {
 #ifdef HAVE_SYS_QUOTAS
        int result;
@@ -64,7 +77,7 @@ static int vfswrap_get_quota(struct vfs_handle_struct *handle,  enum SMB_QUOTA_T
 #endif
 }
 
-static int vfswrap_set_quota(struct vfs_handle_struct *handle,  enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
+static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
 {
 #ifdef HAVE_SYS_QUOTAS
        int result;
@@ -79,13 +92,16 @@ static int vfswrap_set_quota(struct vfs_handle_struct *handle,  enum SMB_QUOTA_T
 #endif
 }
 
-static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, bool labels)
+static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
+                                       struct files_struct *fsp,
+                                       struct shadow_copy_data *shadow_copy_data,
+                                       bool labels)
 {
        errno = ENOSYS;
        return -1;  /* Not implemented. */
 }
 
-static int vfswrap_statvfs(struct vfs_handle_struct *handle,  const char *path, vfs_statvfs_struct *statbuf)
+static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
 {
        return sys_statvfs(path, statbuf);
 }
@@ -96,27 +112,23 @@ static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
        connection_struct *conn = handle->conn;
        uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
        struct smb_filename *smb_fname_cpath = NULL;
-       NTSTATUS status;
-       int ret = -1;
-
-#if defined(DARWINOS)
        struct vfs_statvfs_struct statbuf;
+       int ret;
+
        ZERO_STRUCT(statbuf);
-       sys_statvfs(conn->connectpath, &statbuf);
-       caps = statbuf.FsCapabilities;
-#endif
+       ret = sys_statvfs(conn->connectpath, &statbuf);
+       if (ret == 0) {
+               caps = statbuf.FsCapabilities;
+       }
 
        *p_ts_res = TIMESTAMP_SET_SECONDS;
 
        /* Work out what timestamp resolution we can
         * use when setting a timestamp. */
 
-       status = create_synthetic_smb_fname(talloc_tos(),
-                               conn->connectpath,
-                               NULL,
-                               NULL,
-                               &smb_fname_cpath);
-       if (!NT_STATUS_IS_OK(status)) {
+       smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
+                                             NULL, NULL);
+       if (smb_fname_cpath == NULL) {
                return caps;
        }
 
@@ -148,65 +160,273 @@ static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
                        "resolution of %s "
                        "available on share %s, directory %s\n",
                        *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
-                       lp_servicename(conn->params->service),
+                       lp_servicename(talloc_tos(), conn->params->service),
                        conn->connectpath ));
        }
        TALLOC_FREE(smb_fname_cpath);
        return caps;
 }
 
+static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
+                                         struct dfs_GetDFSReferral *r)
+{
+       struct junction_map *junction = NULL;
+       int consumedcnt = 0;
+       bool self_referral = false;
+       char *pathnamep = NULL;
+       char *local_dfs_path = NULL;
+       NTSTATUS status;
+       int i;
+       uint16_t max_referral_level = r->in.req.max_referral_level;
+
+       if (DEBUGLVL(10)) {
+               NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
+       }
+
+       /* get the junction entry */
+       if (r->in.req.servername == NULL) {
+               return NT_STATUS_NOT_FOUND;
+       }
+
+       /*
+        * Trim pathname sent by client so it begins with only one backslash.
+        * Two backslashes confuse some dfs clients
+        */
+
+       local_dfs_path = talloc_strdup(r, r->in.req.servername);
+       if (local_dfs_path == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       pathnamep = local_dfs_path;
+       while (IS_DIRECTORY_SEP(pathnamep[0]) &&
+              IS_DIRECTORY_SEP(pathnamep[1])) {
+               pathnamep++;
+       }
+
+       junction = talloc_zero(r, struct junction_map);
+       if (junction == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* The following call can change cwd. */
+       status = get_referred_path(r, pathnamep,
+                                  !handle->conn->sconn->using_smb2,
+                                  junction, &consumedcnt, &self_referral);
+       if (!NT_STATUS_IS_OK(status)) {
+               vfs_ChDir(handle->conn, handle->conn->connectpath);
+               return status;
+       }
+       vfs_ChDir(handle->conn, handle->conn->connectpath);
+
+       if (!self_referral) {
+               pathnamep[consumedcnt] = '\0';
+
+               if (DEBUGLVL(3)) {
+                       dbgtext("setup_dfs_referral: Path %s to "
+                               "alternate path(s):",
+                               pathnamep);
+                       for (i=0; i < junction->referral_count; i++) {
+                               dbgtext(" %s",
+                               junction->referral_list[i].alternate_path);
+                       }
+                       dbgtext(".\n");
+               }
+       }
+
+       if (r->in.req.max_referral_level <= 2) {
+               max_referral_level = 2;
+       }
+       if (r->in.req.max_referral_level >= 3) {
+               max_referral_level = 3;
+       }
+
+       r->out.resp = talloc_zero(r, struct dfs_referral_resp);
+       if (r->out.resp == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
+       r->out.resp->nb_referrals = junction->referral_count;
+
+       r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
+       if (self_referral) {
+               r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
+       }
+
+       r->out.resp->referral_entries = talloc_zero_array(r,
+                               struct dfs_referral_type,
+                               r->out.resp->nb_referrals);
+       if (r->out.resp->referral_entries == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       switch (max_referral_level) {
+       case 2:
+               for(i=0; i < junction->referral_count; i++) {
+                       struct referral *ref = &junction->referral_list[i];
+                       TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
+                       struct dfs_referral_type *t =
+                               &r->out.resp->referral_entries[i];
+                       struct dfs_referral_v2 *v2 = &t->referral.v2;
+
+                       t->version = 2;
+                       v2->size = VERSION2_REFERRAL_SIZE;
+                       if (self_referral) {
+                               v2->server_type = DFS_SERVER_ROOT;
+                       } else {
+                               v2->server_type = DFS_SERVER_NON_ROOT;
+                       }
+                       v2->entry_flags = 0;
+                       v2->proximity = ref->proximity;
+                       v2->ttl = ref->ttl;
+                       v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
+                       if (v2->DFS_path == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+                       v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
+                       if (v2->DFS_alt_path == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+                       v2->netw_address = talloc_strdup(mem_ctx,
+                                                        ref->alternate_path);
+                       if (v2->netw_address == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               }
+
+               break;
+       case 3:
+               for(i=0; i < junction->referral_count; i++) {
+                       struct referral *ref = &junction->referral_list[i];
+                       TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
+                       struct dfs_referral_type *t =
+                               &r->out.resp->referral_entries[i];
+                       struct dfs_referral_v3 *v3 = &t->referral.v3;
+                       struct dfs_normal_referral *r1 = &v3->referrals.r1;
+
+                       t->version = 3;
+                       v3->size = VERSION3_REFERRAL_SIZE;
+                       if (self_referral) {
+                               v3->server_type = DFS_SERVER_ROOT;
+                       } else {
+                               v3->server_type = DFS_SERVER_NON_ROOT;
+                       }
+                       v3->entry_flags = 0;
+                       v3->ttl = ref->ttl;
+                       r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
+                       if (r1->DFS_path == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+                       r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
+                       if (r1->DFS_alt_path == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+                       r1->netw_address = talloc_strdup(mem_ctx,
+                                                        ref->alternate_path);
+                       if (r1->netw_address == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               }
+               break;
+       default:
+               DEBUG(0,("setup_dfs_referral: Invalid dfs referral "
+                       "version: %d\n",
+                       max_referral_level));
+               return NT_STATUS_INVALID_LEVEL;
+       }
+
+       if (DEBUGLVL(10)) {
+               NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
+       }
+
+       return NT_STATUS_OK;
+}
+
 /* Directory operations */
 
-static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle,  const char *fname, const char *mask, uint32 attr)
+static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
 {
-       SMB_STRUCT_DIR *result;
+       DIR *result;
 
        START_PROFILE(syscall_opendir);
-       result = sys_opendir(fname);
+       result = opendir(fname);
        END_PROFILE(syscall_opendir);
        return result;
 }
 
-static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle,
-                                         SMB_STRUCT_DIR *dirp,
+static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
+                       files_struct *fsp,
+                       const char *mask,
+                       uint32 attr)
+{
+       DIR *result;
+
+       START_PROFILE(syscall_fdopendir);
+       result = sys_fdopendir(fsp->fh->fd);
+       END_PROFILE(syscall_fdopendir);
+       return result;
+}
+
+
+static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
+                                         DIR *dirp,
                                          SMB_STRUCT_STAT *sbuf)
 {
-       SMB_STRUCT_DIRENT *result;
+       struct dirent *result;
 
        START_PROFILE(syscall_readdir);
-       result = sys_readdir(dirp);
-       /* Default Posix readdir() does not give us stat info.
-        * Set to invalid to indicate we didn't return this info. */
-       if (sbuf)
-               SET_STAT_INVALID(*sbuf);
+       result = readdir(dirp);
        END_PROFILE(syscall_readdir);
+       if (sbuf) {
+               /* Default Posix readdir() does not give us stat info.
+                * Set to invalid to indicate we didn't return this info. */
+               SET_STAT_INVALID(*sbuf);
+#if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
+               if (result != NULL) {
+                       /* See if we can efficiently return this. */
+                       struct stat st;
+                       int flags = (lp_posix_pathnames() ?
+                               AT_SYMLINK_NOFOLLOW : 0);
+                       int ret = fstatat(dirfd(dirp),
+                                       result->d_name,
+                                       &st,
+                                       flags);
+                       if (ret == 0) {
+                               init_stat_ex_from_stat(sbuf,
+                                       &st,
+                                       lp_fake_dir_create_times(
+                                               SNUM(handle->conn)));
+                       }
+               }
+#endif
+       }
        return result;
 }
 
-static void vfswrap_seekdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp, long offset)
+static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
 {
        START_PROFILE(syscall_seekdir);
-       sys_seekdir(dirp, offset);
+       seekdir(dirp, offset);
        END_PROFILE(syscall_seekdir);
 }
 
-static long vfswrap_telldir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
+static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
 {
        long result;
        START_PROFILE(syscall_telldir);
-       result = sys_telldir(dirp);
+       result = telldir(dirp);
        END_PROFILE(syscall_telldir);
        return result;
 }
 
-static void vfswrap_rewinddir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
+static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
 {
        START_PROFILE(syscall_rewinddir);
-       sys_rewinddir(dirp);
+       rewinddir(dirp);
        END_PROFILE(syscall_rewinddir);
 }
 
-static int vfswrap_mkdir(vfs_handle_struct *handle,  const char *path, mode_t mode)
+static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
 {
        int result;
        bool has_dacl = False;
@@ -217,7 +437,7 @@ static int vfswrap_mkdir(vfs_handle_struct *handle,  const char *path, mode_t mo
        if (lp_inherit_acls(SNUM(handle->conn))
            && parent_dirname(talloc_tos(), path, &parent, NULL)
            && (has_dacl = directory_has_default_acl(handle->conn, parent)))
-               mode = 0777;
+               mode = (0777 & lp_dir_mask(SNUM(handle->conn)));
 
        TALLOC_FREE(parent);
 
@@ -240,7 +460,7 @@ static int vfswrap_mkdir(vfs_handle_struct *handle,  const char *path, mode_t mo
        return result;
 }
 
-static int vfswrap_rmdir(vfs_handle_struct *handle,  const char *path)
+static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
 {
        int result;
 
@@ -250,18 +470,18 @@ static int vfswrap_rmdir(vfs_handle_struct *handle,  const char *path)
        return result;
 }
 
-static int vfswrap_closedir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
+static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
 {
        int result;
 
        START_PROFILE(syscall_closedir);
-       result = sys_closedir(dirp);
+       result = closedir(dirp);
        END_PROFILE(syscall_closedir);
        return result;
 }
 
 static void vfswrap_init_search_op(vfs_handle_struct *handle,
-                                  SMB_STRUCT_DIR *dirp)
+                                  DIR *dirp)
 {
        /* Default behavior is a NOOP */
 }
@@ -281,7 +501,7 @@ static int vfswrap_open(vfs_handle_struct *handle,
                goto out;
        }
 
-       result = sys_open(smb_fname->base_name, flags, mode);
+       result = open(smb_fname->base_name, flags, mode);
  out:
        END_PROFILE(syscall_open);
        return result;
@@ -298,6 +518,7 @@ static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
                                    uint32_t file_attributes,
                                    uint32_t oplock_request,
                                    uint64_t allocation_size,
+                                   uint32_t private_flags,
                                    struct security_descriptor *sd,
                                    struct ea_list *ea_list,
                                    files_struct **result,
@@ -307,7 +528,8 @@ static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
                                   access_mask, share_access,
                                   create_disposition, create_options,
                                   file_attributes, oplock_request,
-                                  allocation_size, sd, ea_list, result,
+                                  allocation_size, private_flags,
+                                  sd, ea_list, result,
                                   pinfo);
 }
 
@@ -332,7 +554,7 @@ static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *
 }
 
 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
-                       size_t n, SMB_OFF_T offset)
+                       size_t n, off_t offset)
 {
        ssize_t result;
 
@@ -348,7 +570,7 @@ static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void
        }
 
 #else /* HAVE_PREAD */
-       SMB_OFF_T   curr;
+       off_t   curr;
        int lerrno;
 
        curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
@@ -386,7 +608,7 @@ static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const
 }
 
 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
-                       size_t n, SMB_OFF_T offset)
+                       size_t n, off_t offset)
 {
        ssize_t result;
 
@@ -401,7 +623,7 @@ static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, cons
        }
 
 #else /* HAVE_PWRITE */
-       SMB_OFF_T   curr;
+       off_t   curr;
        int         lerrno;
 
        curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
@@ -424,15 +646,229 @@ static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, cons
        return result;
 }
 
-static SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T offset, int whence)
+static void vfswrap_asys_finished(struct tevent_context *ev,
+                                 struct tevent_fd *fde,
+                                 uint16_t flags, void *p);
+
+static bool vfswrap_init_asys_ctx(struct smbXsrv_connection *conn)
+{
+       int ret;
+       int fd;
+
+       if (conn->asys_ctx != NULL) {
+               return true;
+       }
+       ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
+       if (ret != 0) {
+               DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
+               return false;
+       }
+
+       fd = asys_signalfd(conn->asys_ctx);
+
+       set_blocking(fd, false);
+
+       conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
+                                      TEVENT_FD_READ,
+                                      vfswrap_asys_finished,
+                                      conn->asys_ctx);
+       if (conn->asys_fde == NULL) {
+               DEBUG(1, ("tevent_add_fd failed\n"));
+               asys_context_destroy(conn->asys_ctx);
+               conn->asys_ctx = NULL;
+               return false;
+       }
+       return true;
+}
+
+struct vfswrap_asys_state {
+       struct asys_context *asys_ctx;
+       struct tevent_req *req;
+       ssize_t ret;
+       int err;
+};
+
+static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
+{
+       asys_cancel(s->asys_ctx, s->req);
+       return 0;
+}
+
+static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
+                                            TALLOC_CTX *mem_ctx,
+                                            struct tevent_context *ev,
+                                            struct files_struct *fsp,
+                                            void *data,
+                                            size_t n, off_t offset)
+{
+       struct tevent_req *req;
+       struct vfswrap_asys_state *state;
+       int ret;
+
+       req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
+               tevent_req_oom(req);
+               return tevent_req_post(req, ev);
+       }
+       state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
+       state->req = req;
+
+       ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
+       if (ret != 0) {
+               tevent_req_error(req, ret);
+               return tevent_req_post(req, ev);
+       }
+       talloc_set_destructor(state, vfswrap_asys_state_destructor);
+
+       return req;
+}
+
+static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
+                                             TALLOC_CTX *mem_ctx,
+                                             struct tevent_context *ev,
+                                             struct files_struct *fsp,
+                                             const void *data,
+                                             size_t n, off_t offset)
+{
+       struct tevent_req *req;
+       struct vfswrap_asys_state *state;
+       int ret;
+
+       req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
+               tevent_req_oom(req);
+               return tevent_req_post(req, ev);
+       }
+       state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
+       state->req = req;
+
+       ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
+       if (ret != 0) {
+               tevent_req_error(req, ret);
+               return tevent_req_post(req, ev);
+       }
+       talloc_set_destructor(state, vfswrap_asys_state_destructor);
+
+       return req;
+}
+
+static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
+                                            TALLOC_CTX *mem_ctx,
+                                            struct tevent_context *ev,
+                                            struct files_struct *fsp)
+{
+       struct tevent_req *req;
+       struct vfswrap_asys_state *state;
+       int ret;
+
+       req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
+               tevent_req_oom(req);
+               return tevent_req_post(req, ev);
+       }
+       state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
+       state->req = req;
+
+       ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
+       if (ret != 0) {
+               tevent_req_error(req, ret);
+               return tevent_req_post(req, ev);
+       }
+       talloc_set_destructor(state, vfswrap_asys_state_destructor);
+
+       return req;
+}
+
+static void vfswrap_asys_finished(struct tevent_context *ev,
+                                       struct tevent_fd *fde,
+                                       uint16_t flags, void *p)
+{
+       struct asys_context *asys_ctx = (struct asys_context *)p;
+       struct tevent_req *req;
+       struct vfswrap_asys_state *state;
+       int res;
+       ssize_t ret;
+       int err;
+       void *private_data;
+
+       if ((flags & TEVENT_FD_READ) == 0) {
+               return;
+       }
+
+       while (true) {
+               res = asys_result(asys_ctx, &ret, &err, &private_data);
+               if (res == EINTR || res == EAGAIN) {
+                       return;
+               }
+#ifdef EWOULDBLOCK
+               if (res == EWOULDBLOCK) {
+                       return;
+               }
+#endif
+
+               if (res == ECANCELED) {
+                       return;
+               }
+
+               if (res != 0) {
+                       DEBUG(1, ("asys_result returned %s\n", strerror(res)));
+                       return;
+               }
+
+               req = talloc_get_type_abort(private_data, struct tevent_req);
+               state = tevent_req_data(req, struct vfswrap_asys_state);
+
+               talloc_set_destructor(state, NULL);
+
+               state->ret = ret;
+               state->err = err;
+               tevent_req_defer_callback(req, ev);
+               tevent_req_done(req);
+       }
+}
+
+static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
+{
+       struct vfswrap_asys_state *state = tevent_req_data(
+               req, struct vfswrap_asys_state);
+
+       if (tevent_req_is_unix_error(req, err)) {
+               return -1;
+       }
+       *err = state->err;
+       return state->ret;
+}
+
+static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
 {
-       SMB_OFF_T result = 0;
+       struct vfswrap_asys_state *state = tevent_req_data(
+               req, struct vfswrap_asys_state);
+
+       if (tevent_req_is_unix_error(req, err)) {
+               return -1;
+       }
+       *err = state->err;
+       return state->ret;
+}
+
+static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
+{
+       off_t result = 0;
 
        START_PROFILE(syscall_lseek);
 
        /* Cope with 'stat' file opens. */
        if (fsp->fh->fd != -1)
-               result = sys_lseek(fsp->fh->fd, offset, whence);
+               result = lseek(fsp->fh->fd, offset, whence);
 
        /*
         * We want to maintain the fiction that we can seek
@@ -451,7 +887,7 @@ static SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, SMB
 }
 
 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
-                       SMB_OFF_T offset, size_t n)
+                       off_t offset, size_t n)
 {
        ssize_t result;
 
@@ -464,7 +900,7 @@ static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struc
 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
                        int fromfd,
                        files_struct *tofsp,
-                       SMB_OFF_T offset,
+                       off_t offset,
                        size_t n)
 {
        ssize_t result;
@@ -475,190 +911,582 @@ static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
        return result;
 }
 
-/*********************************************************
- For rename across filesystems Patch from Warren Birnbaum
- <warrenb@hpcvscdp.cv.hp.com>
-**********************************************************/
-
-static int copy_reg(const char *source, const char *dest)
+static int vfswrap_rename(vfs_handle_struct *handle,
+                         const struct smb_filename *smb_fname_src,
+                         const struct smb_filename *smb_fname_dst)
 {
-       SMB_STRUCT_STAT source_stats;
-       int saved_errno;
-       int ifd = -1;
-       int ofd = -1;
+       int result = -1;
 
-       if (sys_lstat(source, &source_stats, false) == -1)
-               return -1;
+       START_PROFILE(syscall_rename);
 
-       if (!S_ISREG (source_stats.st_ex_mode))
-               return -1;
+       if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
+               errno = ENOENT;
+               goto out;
+       }
 
-       if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
-               return -1;
+       result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
 
-       if (unlink (dest) && errno != ENOENT)
-               return -1;
+ out:
+       END_PROFILE(syscall_rename);
+       return result;
+}
+
+static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
+{
+#ifdef HAVE_FSYNC
+       int result;
 
-#ifdef O_NOFOLLOW
-       if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
+       START_PROFILE(syscall_fsync);
+       result = fsync(fsp->fh->fd);
+       END_PROFILE(syscall_fsync);
+       return result;
 #else
-       if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
+       return 0;
 #endif
-               goto err;
+}
 
-       if (transfer_file(ifd, ofd, (size_t)-1) == -1)
-               goto err;
+static int vfswrap_stat(vfs_handle_struct *handle,
+                       struct smb_filename *smb_fname)
+{
+       int result = -1;
 
-       /*
-        * Try to preserve ownership.  For non-root it might fail, but that's ok.
-        * But root probably wants to know, e.g. if NFS disallows it.
-        */
+       START_PROFILE(syscall_stat);
 
-#ifdef HAVE_FCHOWN
-       if ((fchown(ofd, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM))
-#else
-       if ((chown(dest, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM))
-#endif
-               goto err;
+       if (smb_fname->stream_name) {
+               errno = ENOENT;
+               goto out;
+       }
 
-       /*
-        * fchown turns off set[ug]id bits for non-root,
-        * so do the chmod last.
-        */
+       result = sys_stat(smb_fname->base_name, &smb_fname->st,
+                         lp_fake_dir_create_times(SNUM(handle->conn)));
+ out:
+       END_PROFILE(syscall_stat);
+       return result;
+}
 
-#if defined(HAVE_FCHMOD)
-       if (fchmod (ofd, source_stats.st_ex_mode & 07777))
-#else
-       if (chmod (dest, source_stats.st_ex_mode & 07777))
-#endif
-               goto err;
+static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
+{
+       int result;
 
-       if (close (ifd) == -1)
-               goto err;
+       START_PROFILE(syscall_fstat);
+       result = sys_fstat(fsp->fh->fd,
+                          sbuf, lp_fake_dir_create_times(SNUM(handle->conn)));
+       END_PROFILE(syscall_fstat);
+       return result;
+}
 
-       if (close (ofd) == -1)
-               return -1;
+static int vfswrap_lstat(vfs_handle_struct *handle,
+                        struct smb_filename *smb_fname)
+{
+       int result = -1;
+
+       START_PROFILE(syscall_lstat);
+
+       if (smb_fname->stream_name) {
+               errno = ENOENT;
+               goto out;
+       }
+
+       result = sys_lstat(smb_fname->base_name, &smb_fname->st,
+                          lp_fake_dir_create_times(SNUM(handle->conn)));
+ out:
+       END_PROFILE(syscall_lstat);
+       return result;
+}
+
+static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
+                                      const char *name,
+                                      enum vfs_translate_direction direction,
+                                      TALLOC_CTX *mem_ctx,
+                                      char **mapped_name)
+{
+       return NT_STATUS_NONE_MAPPED;
+}
 
-       /* Try to copy the old file's modtime and access time.  */
+/*
+ * Implement the default fsctl operation.
+ */
+static bool vfswrap_logged_ioctl_message = false;
+
+static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
+                             struct files_struct *fsp,
+                             TALLOC_CTX *ctx,
+                             uint32_t function,
+                             uint16_t req_flags, /* Needed for UNICODE ... */
+                             const uint8_t *_in_data,
+                             uint32_t in_len,
+                             uint8_t **_out_data,
+                             uint32_t max_out_len,
+                             uint32_t *out_len)
+{
+       const char *in_data = (const char *)_in_data;
+       char **out_data = (char **)_out_data;
+
+       switch (function) {
+       case FSCTL_SET_SPARSE:
        {
-               struct utimbuf tv;
+               bool set_sparse = true;
+               NTSTATUS status;
+
+               if (in_len >= 1 && in_data[0] == 0) {
+                       set_sparse = false;
+               }
+
+               status = file_set_sparse(handle->conn, fsp, set_sparse);
+               
+               DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
+                     ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
+                      smb_fname_str_dbg(fsp->fsp_name), set_sparse, 
+                      nt_errstr(status)));
 
-               tv.actime = convert_timespec_to_time_t(source_stats.st_ex_atime);
-               tv.modtime = convert_timespec_to_time_t(source_stats.st_ex_mtime);
-               utime(dest, &tv);
+               return status;
        }
 
-       if (unlink (source) == -1)
-               return -1;
+       case FSCTL_CREATE_OR_GET_OBJECT_ID:
+       {
+               unsigned char objid[16];
+               char *return_data = NULL;
 
-       return 0;
+               /* This should return the object-id on this file.
+                * I think I'll make this be the inode+dev. JRA.
+                */
 
-  err:
+               DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
+                         fsp_fnum_dbg(fsp)));
 
-       saved_errno = errno;
-       if (ifd != -1)
-               close(ifd);
-       if (ofd != -1)
-               close(ofd);
-       errno = saved_errno;
-       return -1;
-}
+               *out_len = (max_out_len >= 64) ? 64 : max_out_len;
+               /* Hmmm, will this cause problems if less data asked for? */
+               return_data = talloc_array(ctx, char, 64);
+               if (return_data == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
 
-static int vfswrap_rename(vfs_handle_struct *handle,
-                         const struct smb_filename *smb_fname_src,
-                         const struct smb_filename *smb_fname_dst)
-{
-       int result = -1;
+               /* For backwards compatibility only store the dev/inode. */
+               push_file_id_16(return_data, &fsp->file_id);
+               memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
+               push_file_id_16(return_data+32, &fsp->file_id);
+               *out_data = return_data;
+               return NT_STATUS_OK;
+       }
 
-       START_PROFILE(syscall_rename);
+       case FSCTL_GET_REPARSE_POINT:
+       {
+               /* Fail it with STATUS_NOT_A_REPARSE_POINT */
+               DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
+                          "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
+               return NT_STATUS_NOT_A_REPARSE_POINT;
+       }
 
-       if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
-               errno = ENOENT;
-               goto out;
+       case FSCTL_SET_REPARSE_POINT:
+       {
+               /* Fail it with STATUS_NOT_A_REPARSE_POINT */
+               DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
+                          "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
+               return NT_STATUS_NOT_A_REPARSE_POINT;
        }
 
-       result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
-       if ((result == -1) && (errno == EXDEV)) {
-               /* Rename across filesystems needed. */
-               result = copy_reg(smb_fname_src->base_name,
-                                 smb_fname_dst->base_name);
+       case FSCTL_GET_SHADOW_COPY_DATA:
+       {
+               /*
+                * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
+                * and return their volume names.  If max_data_count is 16, then it is just
+                * asking for the number of volumes and length of the combined names.
+                *
+                * pdata is the data allocated by our caller, but that uses
+                * total_data_count (which is 0 in our case) rather than max_data_count.
+                * Allocate the correct amount and return the pointer to let
+                * it be deallocated when we return.
+                */
+               struct shadow_copy_data *shadow_data = NULL;
+               bool labels = False;
+               uint32 labels_data_count = 0;
+               uint32 i;
+               char *cur_pdata = NULL;
+
+               if (max_out_len < 16) {
+                       DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
+                               max_out_len));
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               if (max_out_len > 16) {
+                       labels = True;
+               }
+
+               shadow_data = talloc_zero(ctx, struct shadow_copy_data);
+               if (shadow_data == NULL) {
+                       DEBUG(0,("TALLOC_ZERO() failed!\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               /*
+                * Call the VFS routine to actually do the work.
+                */
+               if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
+                       TALLOC_FREE(shadow_data);
+                       if (errno == ENOSYS) {
+                               DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n", 
+                                       fsp->conn->connectpath));
+                               return NT_STATUS_NOT_SUPPORTED;
+                       } else {
+                               DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n", 
+                                       fsp->conn->connectpath));
+                               return NT_STATUS_UNSUCCESSFUL;
+                       }
+               }
+
+               labels_data_count = (shadow_data->num_volumes * 2 * 
+                                       sizeof(SHADOW_COPY_LABEL)) + 2;
+
+               if (!labels) {
+                       *out_len = 16;
+               } else {
+                       *out_len = 12 + labels_data_count + 4;
+               }
+
+               if (max_out_len < *out_len) {
+                       DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
+                               max_out_len, *out_len));
+                       TALLOC_FREE(shadow_data);
+                       return NT_STATUS_BUFFER_TOO_SMALL;
+               }
+
+               cur_pdata = talloc_array(ctx, char, *out_len);
+               if (cur_pdata == NULL) {
+                       TALLOC_FREE(shadow_data);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               *out_data = cur_pdata;
+
+               /* num_volumes 4 bytes */
+               SIVAL(cur_pdata, 0, shadow_data->num_volumes);
+
+               if (labels) {
+                       /* num_labels 4 bytes */
+                       SIVAL(cur_pdata, 4, shadow_data->num_volumes);
+               }
+
+               /* needed_data_count 4 bytes */
+               SIVAL(cur_pdata, 8, labels_data_count + 4);
+
+               cur_pdata += 12;
+
+               DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
+                         shadow_data->num_volumes, fsp_str_dbg(fsp)));
+               if (labels && shadow_data->labels) {
+                       for (i=0; i<shadow_data->num_volumes; i++) {
+                               srvstr_push(cur_pdata, req_flags,
+                                           cur_pdata, shadow_data->labels[i],
+                                           2 * sizeof(SHADOW_COPY_LABEL),
+                                           STR_UNICODE|STR_TERMINATE);
+                               cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
+                               DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
+                       }
+               }
+
+               TALLOC_FREE(shadow_data);
+
+               return NT_STATUS_OK;
        }
 
- out:
-       END_PROFILE(syscall_rename);
-       return result;
+       case FSCTL_FIND_FILES_BY_SID:
+       {
+               /* pretend this succeeded -
+                *
+                * we have to send back a list with all files owned by this SID
+                *
+                * but I have to check that --metze
+                */
+               struct dom_sid sid;
+               uid_t uid;
+               size_t sid_len;
+
+               DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
+                          fsp_fnum_dbg(fsp)));
+
+               if (in_len < 8) {
+                       /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               sid_len = MIN(in_len - 4,SID_MAX_SIZE);
+
+               /* unknown 4 bytes: this is not the length of the sid :-(  */
+               /*unknown = IVAL(pdata,0);*/
+
+               if (!sid_parse(in_data + 4, sid_len, &sid)) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
+
+               if (!sid_to_uid(&sid, &uid)) {
+                       DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
+                                sid_string_dbg(&sid),
+                                (unsigned long)sid_len));
+                       uid = (-1);
+               }
+
+               /* we can take a look at the find source :-)
+                *
+                * find ./ -uid $uid  -name '*'   is what we need here
+                *
+                *
+                * and send 4bytes len and then NULL terminated unicode strings
+                * for each file
+                *
+                * but I don't know how to deal with the paged results
+                * (maybe we can hang the result anywhere in the fsp struct)
+                *
+                * but I don't know how to deal with the paged results
+                * (maybe we can hang the result anywhere in the fsp struct)
+                *
+                * we don't send all files at once
+                * and at the next we should *not* start from the beginning,
+                * so we have to cache the result
+                *
+                * --metze
+                */
+
+               /* this works for now... */
+               return NT_STATUS_OK;
+       }
+
+       case FSCTL_QUERY_ALLOCATED_RANGES:
+       {
+               /* FIXME: This is just a dummy reply, telling that all of the
+                * file is allocated. MKS cp needs that.
+                * Adding the real allocated ranges via FIEMAP on Linux
+                * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
+                * this FSCTL correct for sparse files.
+                */
+               NTSTATUS status;
+               uint64_t offset, length;
+               char *out_data_tmp = NULL;
+
+               if (in_len != 16) {
+                       DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
+                               in_len));
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               if (max_out_len < 16) {
+                       DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
+                               max_out_len));
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               offset = BVAL(in_data,0);
+               length = BVAL(in_data,8);
+
+               if (offset + length < offset) {
+                       /* No 64-bit integer wrap. */
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               /* Shouldn't this be SMB_VFS_STAT ... ? */
+               status = vfs_stat_fsp(fsp);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               *out_len = 16;
+               out_data_tmp = talloc_array(ctx, char, *out_len);
+               if (out_data_tmp == NULL) {
+                       DEBUG(10, ("unable to allocate memory for response\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               if (offset > fsp->fsp_name->st.st_ex_size ||
+                               fsp->fsp_name->st.st_ex_size == 0 ||
+                               length == 0) {
+                       memset(out_data_tmp, 0, *out_len);
+               } else {
+                       uint64_t end = offset + length;
+                       end = MIN(end, fsp->fsp_name->st.st_ex_size);
+                       SBVAL(out_data_tmp, 0, 0);
+                       SBVAL(out_data_tmp, 8, end);
+               }
+
+               *out_data = out_data_tmp;
+
+               return NT_STATUS_OK;
+       }
+
+       case FSCTL_IS_VOLUME_DIRTY:
+       {
+               DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
+                         "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
+               /*
+                * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
+                * says we have to respond with NT_STATUS_INVALID_PARAMETER
+                */
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       default:
+               /* 
+                * Only print once ... unfortunately there could be lots of
+                * different FSCTLs that are called.
+                */
+               if (!vfswrap_logged_ioctl_message) {
+                       vfswrap_logged_ioctl_message = true;
+                       DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
+                       __func__, function));
+               }
+       }
+
+       return NT_STATUS_NOT_SUPPORTED;
 }
 
-static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
-{
-#ifdef HAVE_FSYNC
-       int result;
+struct vfs_cc_state {
+       off_t copied;
+       uint8_t buf[65536];
+};
+
+static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
+                                                 TALLOC_CTX *mem_ctx,
+                                                 struct tevent_context *ev,
+                                                 struct files_struct *src_fsp,
+                                                 off_t src_off,
+                                                 struct files_struct *dest_fsp,
+                                                 off_t dest_off,
+                                                 off_t num)
+{
+       struct tevent_req *req;
+       struct vfs_cc_state *vfs_cc_state;
+       NTSTATUS status;
+
+       DEBUG(10, ("performing server side copy chunk of length %lu\n",
+                  (unsigned long)num));
+
+       req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       status = vfs_stat_fsp(src_fsp);
+       if (tevent_req_nterror(req, status)) {
+               return tevent_req_post(req, ev);
+       }
+
+       if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
+               /*
+                * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
+                *   If the SourceOffset or SourceOffset + Length extends beyond
+                *   the end of file, the server SHOULD<240> treat this as a
+                *   STATUS_END_OF_FILE error.
+                * ...
+                *   <240> Section 3.3.5.15.6: Windows servers will return
+                *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
+                */
+               tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
+               return tevent_req_post(req, ev);
+       }
+
+       /* could use 2.6.33+ sendfile here to do this in kernel */
+       while (vfs_cc_state->copied < num) {
+               ssize_t ret;
+               struct lock_struct lck;
+               int saved_errno;
+
+               off_t this_num = MIN(sizeof(vfs_cc_state->buf),
+                                    num - vfs_cc_state->copied);
+
+               init_strict_lock_struct(src_fsp,
+                                       src_fsp->op->global->open_persistent_id,
+                                       src_off,
+                                       this_num,
+                                       READ_LOCK,
+                                       &lck);
+
+               if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
+                       tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+                       return tevent_req_post(req, ev);
+               }
 
-       START_PROFILE(syscall_fsync);
-       result = fsync(fsp->fh->fd);
-       END_PROFILE(syscall_fsync);
-       return result;
-#else
-       return 0;
-#endif
-}
+               ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
+                                   this_num, src_off);
+               if (ret == -1) {
+                       saved_errno = errno;
+               }
 
-static int vfswrap_stat(vfs_handle_struct *handle,
-                       struct smb_filename *smb_fname)
-{
-       int result = -1;
+               SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
 
-       START_PROFILE(syscall_stat);
+               if (ret == -1) {
+                       errno = saved_errno;
+                       tevent_req_nterror(req, map_nt_error_from_unix(errno));
+                       return tevent_req_post(req, ev);
+               }
+               if (ret != this_num) {
+                       /* zero tolerance for short reads */
+                       tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
+                       return tevent_req_post(req, ev);
+               }
 
-       if (smb_fname->stream_name) {
-               errno = ENOENT;
-               goto out;
-       }
+               src_off += ret;
 
-       result = sys_stat(smb_fname->base_name, &smb_fname->st,
-                         lp_fake_dir_create_times(SNUM(handle->conn)));
- out:
-       END_PROFILE(syscall_stat);
-       return result;
-}
+               init_strict_lock_struct(dest_fsp,
+                                       dest_fsp->op->global->open_persistent_id,
+                                       dest_off,
+                                       this_num,
+                                       WRITE_LOCK,
+                                       &lck);
 
-static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
-{
-       int result;
+               if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
+                       tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+                       return tevent_req_post(req, ev);
+               }
 
-       START_PROFILE(syscall_fstat);
-       result = sys_fstat(fsp->fh->fd,
-                          sbuf, lp_fake_dir_create_times(SNUM(handle->conn)));
-       END_PROFILE(syscall_fstat);
-       return result;
-}
+               ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
+                                    this_num, dest_off);
+               if (ret == -1) {
+                       saved_errno = errno;
+               }
 
-static int vfswrap_lstat(vfs_handle_struct *handle,
-                        struct smb_filename *smb_fname)
-{
-       int result = -1;
+               SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
 
-       START_PROFILE(syscall_lstat);
+               if (ret == -1) {
+                       errno = saved_errno;
+                       tevent_req_nterror(req, map_nt_error_from_unix(errno));
+                       return tevent_req_post(req, ev);
+               }
+               if (ret != this_num) {
+                       /* zero tolerance for short writes */
+                       tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
+                       return tevent_req_post(req, ev);
+               }
+               dest_off += ret;
 
-       if (smb_fname->stream_name) {
-               errno = ENOENT;
-               goto out;
+               vfs_cc_state->copied += this_num;
        }
 
-       result = sys_lstat(smb_fname->base_name, &smb_fname->st,
-                          lp_fake_dir_create_times(SNUM(handle->conn)));
- out:
-       END_PROFILE(syscall_lstat);
-       return result;
+       tevent_req_done(req);
+       return tevent_req_post(req, ev);
 }
 
-static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
-                                      const char *name,
-                                      enum vfs_translate_direction direction,
-                                      TALLOC_CTX *mem_ctx,
-                                      char **mapped_name)
+static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
+                                       struct tevent_req *req,
+                                       off_t *copied)
 {
-       return NT_STATUS_NONE_MAPPED;
+       struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
+                                                       struct vfs_cc_state);
+       NTSTATUS status;
+
+       if (tevent_req_is_nterror(req, &status)) {
+               DEBUG(2, ("server side copy chunk failed: %s\n",
+                         nt_errstr(status)));
+               *copied = 0;
+               tevent_req_received(req);
+               return status;
+       }
+
+       *copied = vfs_cc_state->copied;
+       DEBUG(10, ("server side copy chunk copied %lu\n",
+                  (unsigned long)*copied));
+       tevent_req_received(req);
+
+       return NT_STATUS_OK;
 }
 
 /********************************************************************
@@ -679,7 +1507,20 @@ static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
        }
 
 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
+       /* The type of st_blocksize is blkcnt_t which *MUST* be
+          signed (according to POSIX) and can be less than 64-bits.
+          Ensure when we're converting to 64 bits wide we don't
+          sign extend. */
+#if defined(SIZEOF_BLKCNT_T_8)
        result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
+#elif defined(SIZEOF_BLKCNT_T_4)
+       {
+               uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
+               result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
+       }
+#else
+#error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
+#endif
 #else
        result = get_file_size_stat(sbuf);
 #endif
@@ -712,7 +1553,7 @@ static int vfswrap_unlink(vfs_handle_struct *handle,
        return result;
 }
 
-static int vfswrap_chmod(vfs_handle_struct *handle,  const char *path, mode_t mode)
+static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
 {
        int result;
 
@@ -808,7 +1649,7 @@ static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid
        return result;
 }
 
-static int vfswrap_chdir(vfs_handle_struct *handle,  const char *path)
+static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
 {
        int result;
 
@@ -818,12 +1659,12 @@ static int vfswrap_chdir(vfs_handle_struct *handle,  const char *path)
        return result;
 }
 
-static char *vfswrap_getwd(vfs_handle_struct *handle,  char *path)
+static char *vfswrap_getwd(vfs_handle_struct *handle)
 {
        char *result;
 
        START_PROFILE(syscall_getwd);
-       result = sys_getwd(path);
+       result = sys_getwd();
        END_PROFILE(syscall_getwd);
        return result;
 }
@@ -846,25 +1687,27 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
                goto out;
        }
 
-       if (null_timespec(ft->atime)) {
-               ft->atime= smb_fname->st.st_ex_atime;
-       }
+       if (ft != NULL) {
+               if (null_timespec(ft->atime)) {
+                       ft->atime= smb_fname->st.st_ex_atime;
+               }
 
-       if (null_timespec(ft->mtime)) {
-               ft->mtime = smb_fname->st.st_ex_mtime;
-       }
+               if (null_timespec(ft->mtime)) {
+                       ft->mtime = smb_fname->st.st_ex_mtime;
+               }
 
-       if (!null_timespec(ft->create_time)) {
-               set_create_timespec_ea(handle->conn,
-                               smb_fname,
-                               ft->create_time);
-       }
+               if (!null_timespec(ft->create_time)) {
+                       set_create_timespec_ea(handle->conn,
+                                              smb_fname,
+                                              ft->create_time);
+               }
 
-       if ((timespec_compare(&ft->atime,
-                               &smb_fname->st.st_ex_atime) == 0) &&
-                       (timespec_compare(&ft->mtime,
-                               &smb_fname->st.st_ex_mtime) == 0)) {
-               return 0;
+               if ((timespec_compare(&ft->atime,
+                                     &smb_fname->st.st_ex_atime) == 0) &&
+                   (timespec_compare(&ft->mtime,
+                                     &smb_fname->st.st_ex_mtime) == 0)) {
+                       return 0;
+               }
        }
 
 #if defined(HAVE_UTIMENSAT)
@@ -876,7 +1719,11 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
        } else {
                result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
        }
-#elif defined(HAVE_UTIMES)
+       if (!((result == -1) && (errno == ENOSYS))) {
+               goto out;
+       }
+#endif
+#if defined(HAVE_UTIMES)
        if (ft != NULL) {
                struct timeval tv[2];
                tv[0] = convert_timespec_to_timeval(ft->atime);
@@ -885,7 +1732,11 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
        } else {
                result = utimes(smb_fname->base_name, NULL);
        }
-#elif defined(HAVE_UTIME)
+       if (!((result == -1) && (errno == ENOSYS))) {
+               goto out;
+       }
+#endif
+#if defined(HAVE_UTIME)
        if (ft != NULL) {
                struct utimbuf times;
                times.actime = convert_timespec_to_time_t(ft->atime);
@@ -894,10 +1745,12 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
        } else {
                result = utime(smb_fname->base_name, NULL);
        }
-#else
+       if (!((result == -1) && (errno == ENOSYS))) {
+               goto out;
+       }
+#endif
        errno = ENOSYS;
        result = -1;
-#endif
 
  out:
        END_PROFILE(syscall_ntimes);
@@ -909,55 +1762,53 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
  allocate is set.
 **********************************************************************/
 
-static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
+static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
 {
-       SMB_STRUCT_STAT st;
-       SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
-       unsigned char zero_space[4096];
-       SMB_OFF_T space_to_write;
+       off_t space_to_write;
        uint64_t space_avail;
        uint64_t bsize,dfree,dsize;
+       int ret;
+       NTSTATUS status;
+       SMB_STRUCT_STAT *pst;
 
-       if (currpos == -1)
-               return -1;
-
-       if (SMB_VFS_FSTAT(fsp, &st) == -1)
+       status = vfs_stat_fsp(fsp);
+       if (!NT_STATUS_IS_OK(status)) {
                return -1;
+       }
+       pst = &fsp->fsp_name->st;
 
 #ifdef S_ISFIFO
-       if (S_ISFIFO(st.st_ex_mode))
+       if (S_ISFIFO(pst->st_ex_mode))
                return 0;
 #endif
 
-       if (st.st_ex_size == len)
+       if (pst->st_ex_size == len)
                return 0;
 
        /* Shrink - just ftruncate. */
-       if (st.st_ex_size > len)
-               return sys_ftruncate(fsp->fh->fd, len);
+       if (pst->st_ex_size > len)
+               return ftruncate(fsp->fh->fd, len);
+
+       space_to_write = len - pst->st_ex_size;
 
-       /* for allocation try posix_fallocate first. This can fail on some
+       /* for allocation try fallocate first. This can fail on some
           platforms e.g. when the filesystem doesn't support it and no
           emulation is being done by the libc (like on AIX with JFS1). In that
-          case we do our own emulation. posix_fallocate implementations can
+          case we do our own emulation. fallocate implementations can
           return ENOTSUP or EINVAL in cases like that. */
-#if defined(HAVE_POSIX_FALLOCATE)
-       {
-               int ret = sys_posix_fallocate(fsp->fh->fd, 0, len);
-               if (ret == ENOSPC) {
-                       errno = ENOSPC;
-                       return -1;
-               }
-               if (ret == 0) {
-                       return 0;
-               }
-               DEBUG(10,("strict_allocate_ftruncate: sys_posix_fallocate "
-                       "failed with error %d. "
-                       "Falling back to slow manual allocation\n", ret));
+       ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
+                               pst->st_ex_size, space_to_write);
+       if (ret == ENOSPC) {
+               errno = ENOSPC;
+               return -1;
        }
-#endif
+       if (ret == 0) {
+               return 0;
+       }
+       DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
+               "error %d. Falling back to slow manual allocation\n", ret));
+
        /* available disk space is enough or not? */
-       space_to_write = len - st.st_ex_size;
        space_avail = get_dfree_info(fsp->conn,
                                     fsp->fsp_name->base_name, false,
                                     &bsize,&dfree,&dsize);
@@ -969,95 +1820,75 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
        }
 
        /* Write out the real space on disk. */
-       if (SMB_VFS_LSEEK(fsp, st.st_ex_size, SEEK_SET) != st.st_ex_size)
-               return -1;
-
-       memset(zero_space, '\0', sizeof(zero_space));
-       while ( space_to_write > 0) {
-               SMB_OFF_T retlen;
-               SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
-
-               retlen = SMB_VFS_WRITE(fsp,(char *)zero_space,current_len_to_write);
-               if (retlen <= 0)
-                       return -1;
-
-               space_to_write -= retlen;
+       ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
+       if (ret != 0) {
+               errno = ret;
+               ret = -1;
        }
 
-       /* Seek to where we were */
-       if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
-               return -1;
-
        return 0;
 }
 
-static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
+static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
 {
        int result = -1;
-       SMB_STRUCT_STAT st;
+       SMB_STRUCT_STAT *pst;
+       NTSTATUS status;
        char c = 0;
-       SMB_OFF_T currpos;
 
        START_PROFILE(syscall_ftruncate);
 
-       if (lp_strict_allocate(SNUM(fsp->conn))) {
+       if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
                result = strict_allocate_ftruncate(handle, fsp, len);
                END_PROFILE(syscall_ftruncate);
                return result;
        }
 
        /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
-          sys_ftruncate if the system supports it. Then I discovered that
+          ftruncate if the system supports it. Then I discovered that
           you can have some filesystems that support ftruncate
           expansion and some that don't! On Linux fat can't do
           ftruncate extend but ext2 can. */
 
-       result = sys_ftruncate(fsp->fh->fd, len);
+       result = ftruncate(fsp->fh->fd, len);
        if (result == 0)
                goto done;
 
        /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
           extend a file with ftruncate. Provide alternate implementation
           for this */
-       currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
-       if (currpos == -1) {
-               goto done;
-       }
 
        /* Do an fstat to see if the file is longer than the requested
           size in which case the ftruncate above should have
           succeeded or shorter, in which case seek to len - 1 and
           write 1 byte of zero */
-       if (SMB_VFS_FSTAT(fsp, &st) == -1) {
+       status = vfs_stat_fsp(fsp);
+       if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       pst = &fsp->fsp_name->st;
 
 #ifdef S_ISFIFO
-       if (S_ISFIFO(st.st_ex_mode)) {
+       if (S_ISFIFO(pst->st_ex_mode)) {
                result = 0;
                goto done;
        }
 #endif
 
-       if (st.st_ex_size == len) {
+       if (pst->st_ex_size == len) {
                result = 0;
                goto done;
        }
 
-       if (st.st_ex_size > len) {
-               /* the sys_ftruncate should have worked */
+       if (pst->st_ex_size > len) {
+               /* the ftruncate should have worked */
                goto done;
        }
 
-       if (SMB_VFS_LSEEK(fsp, len-1, SEEK_SET) != len -1)
-               goto done;
-
-       if (SMB_VFS_WRITE(fsp, &c, 1)!=1)
+       if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
                goto done;
+       }
 
-       /* Seek to where we were */
-       if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
-               goto done;
        result = 0;
 
   done:
@@ -1066,7 +1897,28 @@ static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_O
        return result;
 }
 
-static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
+static int vfswrap_fallocate(vfs_handle_struct *handle,
+                       files_struct *fsp,
+                       enum vfs_fallocate_mode mode,
+                       off_t offset,
+                       off_t len)
+{
+       int result;
+
+       START_PROFILE(syscall_fallocate);
+       if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
+               result = sys_posix_fallocate(fsp->fh->fd, offset, len);
+       } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
+               result = sys_fallocate(fsp->fh->fd, mode, offset, len);
+       } else {
+               errno = EINVAL;
+               result = -1;
+       }
+       END_PROFILE(syscall_fallocate);
+       return result;
+}
+
+static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
 {
        bool result;
 
@@ -1085,7 +1937,7 @@ static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
        return 0;
 }
 
-static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
+static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
 {
        bool result;
 
@@ -1103,11 +1955,6 @@ static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
        START_PROFILE(syscall_linux_setlease);
 
 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
-       /* first set the signal handler */
-       if(linux_set_lease_sighandler(fsp->fh->fd) == -1) {
-               return -1;
-       }
-
        result = linux_setlease(fsp->fh->fd, leasetype);
 #else
        errno = ENOSYS;
@@ -1116,7 +1963,7 @@ static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
        return result;
 }
 
-static int vfswrap_symlink(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
+static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
 {
        int result;
 
@@ -1126,7 +1973,7 @@ static int vfswrap_symlink(vfs_handle_struct *handle,  const char *oldpath, cons
        return result;
 }
 
-static int vfswrap_readlink(vfs_handle_struct *handle,  const char *path, char *buf, size_t bufsiz)
+static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
 {
        int result;
 
@@ -1136,7 +1983,7 @@ static int vfswrap_readlink(vfs_handle_struct *handle,  const char *path, char *
        return result;
 }
 
-static int vfswrap_link(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
+static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
 {
        int result;
 
@@ -1146,7 +1993,7 @@ static int vfswrap_link(vfs_handle_struct *handle,  const char *oldpath, const c
        return result;
 }
 
-static int vfswrap_mknod(vfs_handle_struct *handle,  const char *pathname, mode_t mode, SMB_DEV_T dev)
+static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
 {
        int result;
 
@@ -1156,19 +2003,34 @@ static int vfswrap_mknod(vfs_handle_struct *handle,  const char *pathname, mode_
        return result;
 }
 
-static char *vfswrap_realpath(vfs_handle_struct *handle,  const char *path, char *resolved_path)
+static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
 {
        char *result;
 
        START_PROFILE(syscall_realpath);
-       result = realpath(path, resolved_path);
+#ifdef REALPATH_TAKES_NULL
+       result = realpath(path, NULL);
+#else
+       result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
+       if (result) {
+               char *resolved_path = realpath(path, result);
+               if (!resolved_path) {
+                       SAFE_FREE(result);
+               } else {
+                       /* SMB_ASSERT(result == resolved_path) ? */
+                       result = resolved_path;
+               }
+       }
+#endif
        END_PROFILE(syscall_realpath);
        return result;
 }
 
 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
                                     struct sys_notify_context *ctx,
-                                    struct notify_entry *e,
+                                    const char *path,
+                                    uint32_t *filter,
+                                    uint32_t *subdir_filter,
                                     void (*callback)(struct sys_notify_context *ctx, 
                                                      void *private_data,
                                                      struct notify_event *ev),
@@ -1183,8 +2045,9 @@ static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
         * Until that is the case, hard-code inotify here.
         */
 #ifdef HAVE_INOTIFY
-       if (lp_kernel_change_notify(ctx->conn->params)) {
-               return inotify_watch(ctx, e, callback, private_data, handle);
+       if (lp_kernel_change_notify(vfs_handle->conn->params)) {
+               return inotify_watch(ctx, path, filter, subdir_filter,
+                                    callback, private_data, handle);
        }
 #endif
        /*
@@ -1228,8 +2091,7 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
                                   struct stream_struct **pstreams)
 {
        SMB_STRUCT_STAT sbuf;
-       unsigned int num_streams = 0;
-       struct stream_struct *streams = NULL;
+       struct stream_struct *tmp_streams = NULL;
        int ret;
 
        if ((fsp != NULL) && (fsp->is_directory)) {
@@ -1264,25 +2126,21 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
                goto done;
        }
 
-       streams = talloc(mem_ctx, struct stream_struct);
-
-       if (streams == NULL) {
+       tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
+                                       (*pnum_streams) + 1);
+       if (tmp_streams == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
-
-       streams->size = sbuf.st_ex_size;
-       streams->alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
-
-       streams->name = talloc_strdup(streams, "::$DATA");
-       if (streams->name == NULL) {
-               TALLOC_FREE(streams);
+       tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
+       if (tmp_streams[*pnum_streams].name == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
+       tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
+       tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
 
-       num_streams = 1;
+       *pnum_streams += 1;
+       *pstreams = tmp_streams;
  done:
-       *pnum_streams = num_streams;
-       *pstreams = streams;
        return NT_STATUS_OK;
 }
 
@@ -1363,29 +2221,35 @@ static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
 
 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
                                    files_struct *fsp,
-                                   uint32 security_info, SEC_DESC **ppdesc)
+                                   uint32 security_info,
+                                   TALLOC_CTX *mem_ctx,
+                                   struct security_descriptor **ppdesc)
 {
        NTSTATUS result;
 
        START_PROFILE(fget_nt_acl);
-       result = posix_fget_nt_acl(fsp, security_info, ppdesc);
+       result = posix_fget_nt_acl(fsp, security_info,
+                                  mem_ctx, ppdesc);
        END_PROFILE(fget_nt_acl);
        return result;
 }
 
 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
                                   const char *name,
-                                  uint32 security_info, SEC_DESC **ppdesc)
+                                  uint32 security_info,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct security_descriptor **ppdesc)
 {
        NTSTATUS result;
 
        START_PROFILE(get_nt_acl);
-       result = posix_get_nt_acl(handle->conn, name, security_info, ppdesc);
+       result = posix_get_nt_acl(handle->conn, name, security_info,
+                                 mem_ctx, ppdesc);
        END_PROFILE(get_nt_acl);
        return result;
 }
 
-static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const SEC_DESC *psd)
+static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
 {
        NTSTATUS result;
 
@@ -1395,7 +2259,16 @@ static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp
        return result;
 }
 
-static int vfswrap_chmod_acl(vfs_handle_struct *handle,  const char *name, mode_t mode)
+static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
+                                  struct smb_filename *file,
+                                  struct security_acl *sacl,
+                                  uint32_t access_requested,
+                                  uint32_t access_denied)
+{
+       return NT_STATUS_OK; /* Nothing to do here ... */
+}
+
+static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
 {
 #ifdef HAVE_NO_ACL
        errno = ENOSYS;
@@ -1425,82 +2298,22 @@ static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode
 #endif
 }
 
-static int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle,  SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
-{
-       return sys_acl_get_entry(theacl, entry_id, entry_p);
-}
-
-static int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
-{
-       return sys_acl_get_tag_type(entry_d, tag_type_p);
-}
-
-static int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
-{
-       return sys_acl_get_permset(entry_d, permset_p);
-}
-
-static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d)
-{
-       return sys_acl_get_qualifier(entry_d);
-}
-
-static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,  const char *path_p, SMB_ACL_TYPE_T type)
+static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
+                                         const char *path_p,
+                                         SMB_ACL_TYPE_T type,
+                                         TALLOC_CTX *mem_ctx)
 {
-       return sys_acl_get_file(handle, path_p, type);
+       return sys_acl_get_file(handle, path_p, type, mem_ctx);
 }
 
-static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
+static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
+                                       files_struct *fsp,
+                                       TALLOC_CTX *mem_ctx)
 {
-       return sys_acl_get_fd(handle, fsp);
+       return sys_acl_get_fd(handle, fsp, mem_ctx);
 }
 
-static int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset)
-{
-       return sys_acl_clear_perms(permset);
-}
-
-static int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
-       return sys_acl_add_perm(permset, perm);
-}
-
-static char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle,  SMB_ACL_T theacl, ssize_t *plen)
-{
-       return sys_acl_to_text(theacl, plen);
-}
-
-static SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle,  int count)
-{
-       return sys_acl_init(count);
-}
-
-static int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle,  SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
-{
-       return sys_acl_create_entry(pacl, pentry);
-}
-
-static int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
-{
-       return sys_acl_set_tag_type(entry, tagtype);
-}
-
-static int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, void *qual)
-{
-       return sys_acl_set_qualifier(entry, qual);
-}
-
-static int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
-{
-       return sys_acl_set_permset(entry, permset);
-}
-
-static int vfswrap_sys_acl_valid(vfs_handle_struct *handle,  SMB_ACL_T theacl )
-{
-       return sys_acl_valid(theacl );
-}
-
-static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,  const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
+static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
 {
        return sys_acl_set_file(handle, name, acltype, theacl);
 }
@@ -1510,148 +2323,53 @@ static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
        return sys_acl_set_fd(handle, fsp, theacl);
 }
 
-static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,  const char *path)
+static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
 {
        return sys_acl_delete_def_file(handle, path);
 }
 
-static int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
-       return sys_acl_get_perm(permset, perm);
-}
-
-static int vfswrap_sys_acl_free_text(vfs_handle_struct *handle,  char *text)
-{
-       return sys_acl_free_text(text);
-}
-
-static int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle,  SMB_ACL_T posix_acl)
-{
-       return sys_acl_free_acl(posix_acl);
-}
-
-static int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle,  void *qualifier, SMB_ACL_TAG_T tagtype)
-{
-       return sys_acl_free_qualifier(qualifier, tagtype);
-}
-
 /****************************************************************
  Extended attribute operations.
 *****************************************************************/
 
 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
 {
-       return sys_getxattr(path, name, value, size);
-}
-
-static ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
-{
-       return sys_lgetxattr(path, name, value, size);
+       return getxattr(path, name, value, size);
 }
 
 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
 {
-       return sys_fgetxattr(fsp->fh->fd, name, value, size);
+       return fgetxattr(fsp->fh->fd, name, value, size);
 }
 
 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
 {
-       return sys_listxattr(path, list, size);
-}
-
-ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
-{
-       return sys_llistxattr(path, list, size);
+       return listxattr(path, list, size);
 }
 
-ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
+static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
 {
-       return sys_flistxattr(fsp->fh->fd, list, size);
+       return flistxattr(fsp->fh->fd, list, size);
 }
 
 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
 {
-       return sys_removexattr(path, name);
-}
-
-static int vfswrap_lremovexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
-{
-       return sys_lremovexattr(path, name);
+       return removexattr(path, name);
 }
 
 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
 {
-       return sys_fremovexattr(fsp->fh->fd, name);
+       return fremovexattr(fsp->fh->fd, name);
 }
 
 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
 {
-       return sys_setxattr(path, name, value, size, flags);
-}
-
-static int vfswrap_lsetxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
-{
-       return sys_lsetxattr(path, name, value, size, flags);
+       return setxattr(path, name, value, size, flags);
 }
 
 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
 {
-       return sys_fsetxattr(fsp->fh->fd, name, value, size, flags);
-}
-
-static int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
-       int ret;
-       /*
-        * aio_read must be done as root, because in the glibc aio
-        * implementation the helper thread needs to be able to send a signal
-        * to the main thread, even when it has done a seteuid() to a
-        * different user.
-        */
-       become_root();
-       ret = sys_aio_read(aiocb);
-       unbecome_root();
-       return ret;
-}
-
-static int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
-       int ret;
-       /*
-        * aio_write must be done as root, because in the glibc aio
-        * implementation the helper thread needs to be able to send a signal
-        * to the main thread, even when it has done a seteuid() to a
-        * different user.
-        */
-       become_root();
-       ret = sys_aio_write(aiocb);
-       unbecome_root();
-       return ret;
-}
-
-static ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
-       return sys_aio_return(aiocb);
-}
-
-static int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
-       return sys_aio_cancel(fsp->fh->fd, aiocb);
-}
-
-static int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
-       return sys_aio_error(aiocb);
-}
-
-static int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb)
-{
-       return sys_aio_fsync(op, aiocb);
-}
-
-static int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout)
-{
-       return sys_aio_suspend(aiocb, n, timeout);
+       return fsetxattr(fsp->fh->fd, name, value, size, flags);
 }
 
 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
@@ -1659,9 +2377,15 @@ static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_str
        return false;
 }
 
-static bool vfswrap_is_offline(struct vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf)
+static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
+                              const struct smb_filename *fname,
+                              SMB_STRUCT_STAT *sbuf)
 {
-       if (ISDOT(path) || ISDOTDOT(path)) {
+       NTSTATUS status;
+       char *path;
+       bool offline = false;
+
+        if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
                return false;
        }
 
@@ -1672,10 +2396,21 @@ static bool vfswrap_is_offline(struct vfs_handle_struct *handle, const char *pat
                return false;
        }
 
-       return (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
+        status = get_full_smb_filename(talloc_tos(), fname, &path);
+        if (!NT_STATUS_IS_OK(status)) {
+                errno = map_errno_from_nt_status(status);
+                return false;
+        }
+
+       offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
+
+       TALLOC_FREE(path);
+
+       return offline;
 }
 
-static int vfswrap_set_offline(struct vfs_handle_struct *handle, const char *path)
+static int vfswrap_set_offline(struct vfs_handle_struct *handle,
+                              const struct smb_filename *fname)
 {
        /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
 #if defined(ENOTSUP)
@@ -1684,141 +2419,164 @@ static int vfswrap_set_offline(struct vfs_handle_struct *handle, const char *pat
        return -1;
 }
 
+static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
+                                      struct files_struct *fsp,
+                                      TALLOC_CTX *mem_ctx,
+                                      DATA_BLOB *cookie)
+{
+       return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
+}
+
+static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
+                                          struct files_struct *fsp,
+                                          const DATA_BLOB old_cookie,
+                                          TALLOC_CTX *mem_ctx,
+                                          DATA_BLOB *new_cookie)
+{
+       return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
+                                             new_cookie);
+}
+
+static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
+                                         struct smb_request *smb1req,
+                                         struct smbXsrv_open *op,
+                                         const DATA_BLOB old_cookie,
+                                         TALLOC_CTX *mem_ctx,
+                                         struct files_struct **fsp,
+                                         DATA_BLOB *new_cookie)
+{
+       return vfs_default_durable_reconnect(handle->conn, smb1req, op,
+                                            old_cookie, mem_ctx,
+                                            fsp, new_cookie);
+}
+
 static struct vfs_fn_pointers vfs_default_fns = {
        /* Disk operations */
 
        .connect_fn = vfswrap_connect,
-       .disconnect = vfswrap_disconnect,
-       .disk_free = vfswrap_disk_free,
-       .get_quota = vfswrap_get_quota,
-       .set_quota = vfswrap_set_quota,
-       .get_shadow_copy_data = vfswrap_get_shadow_copy_data,
-       .statvfs = vfswrap_statvfs,
-       .fs_capabilities = vfswrap_fs_capabilities,
+       .disconnect_fn = vfswrap_disconnect,
+       .disk_free_fn = vfswrap_disk_free,
+       .get_quota_fn = vfswrap_get_quota,
+       .set_quota_fn = vfswrap_set_quota,
+       .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
+       .statvfs_fn = vfswrap_statvfs,
+       .fs_capabilities_fn = vfswrap_fs_capabilities,
+       .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
 
        /* Directory operations */
 
-       .opendir = vfswrap_opendir,
-       .readdir = vfswrap_readdir,
-       .seekdir = vfswrap_seekdir,
-       .telldir = vfswrap_telldir,
-       .rewind_dir = vfswrap_rewinddir,
-       .mkdir = vfswrap_mkdir,
-       .rmdir = vfswrap_rmdir,
-       .closedir = vfswrap_closedir,
-       .init_search_op = vfswrap_init_search_op,
+       .opendir_fn = vfswrap_opendir,
+       .fdopendir_fn = vfswrap_fdopendir,
+       .readdir_fn = vfswrap_readdir,
+       .seekdir_fn = vfswrap_seekdir,
+       .telldir_fn = vfswrap_telldir,
+       .rewind_dir_fn = vfswrap_rewinddir,
+       .mkdir_fn = vfswrap_mkdir,
+       .rmdir_fn = vfswrap_rmdir,
+       .closedir_fn = vfswrap_closedir,
+       .init_search_op_fn = vfswrap_init_search_op,
 
        /* File operations */
 
-       .open = vfswrap_open,
-       .create_file = vfswrap_create_file,
+       .open_fn = vfswrap_open,
+       .create_file_fn = vfswrap_create_file,
        .close_fn = vfswrap_close,
-       .vfs_read = vfswrap_read,
-       .pread = vfswrap_pread,
-       .write = vfswrap_write,
-       .pwrite = vfswrap_pwrite,
-       .lseek = vfswrap_lseek,
-       .sendfile = vfswrap_sendfile,
-       .recvfile = vfswrap_recvfile,
-       .rename = vfswrap_rename,
-       .fsync = vfswrap_fsync,
-       .stat = vfswrap_stat,
-       .fstat = vfswrap_fstat,
-       .lstat = vfswrap_lstat,
-       .get_alloc_size = vfswrap_get_alloc_size,
-       .unlink = vfswrap_unlink,
-       .chmod = vfswrap_chmod,
-       .fchmod = vfswrap_fchmod,
-       .chown = vfswrap_chown,
-       .fchown = vfswrap_fchown,
-       .lchown = vfswrap_lchown,
-       .chdir = vfswrap_chdir,
-       .getwd = vfswrap_getwd,
-       .ntimes = vfswrap_ntimes,
-       .ftruncate = vfswrap_ftruncate,
-       .lock = vfswrap_lock,
-       .kernel_flock = vfswrap_kernel_flock,
-       .linux_setlease = vfswrap_linux_setlease,
-       .getlock = vfswrap_getlock,
-       .symlink = vfswrap_symlink,
-       .vfs_readlink = vfswrap_readlink,
-       .link = vfswrap_link,
-       .mknod = vfswrap_mknod,
-       .realpath = vfswrap_realpath,
-       .notify_watch = vfswrap_notify_watch,
-       .chflags = vfswrap_chflags,
-       .file_id_create = vfswrap_file_id_create,
-       .streaminfo = vfswrap_streaminfo,
-       .get_real_filename = vfswrap_get_real_filename,
-       .connectpath = vfswrap_connectpath,
-       .brl_lock_windows = vfswrap_brl_lock_windows,
-       .brl_unlock_windows = vfswrap_brl_unlock_windows,
-       .brl_cancel_windows = vfswrap_brl_cancel_windows,
-       .strict_lock = vfswrap_strict_lock,
-       .strict_unlock = vfswrap_strict_unlock,
-       .translate_name = vfswrap_translate_name,
+       .read_fn = vfswrap_read,
+       .pread_fn = vfswrap_pread,
+       .pread_send_fn = vfswrap_pread_send,
+       .pread_recv_fn = vfswrap_asys_ssize_t_recv,
+       .write_fn = vfswrap_write,
+       .pwrite_fn = vfswrap_pwrite,
+       .pwrite_send_fn = vfswrap_pwrite_send,
+       .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
+       .lseek_fn = vfswrap_lseek,
+       .sendfile_fn = vfswrap_sendfile,
+       .recvfile_fn = vfswrap_recvfile,
+       .rename_fn = vfswrap_rename,
+       .fsync_fn = vfswrap_fsync,
+       .fsync_send_fn = vfswrap_fsync_send,
+       .fsync_recv_fn = vfswrap_asys_int_recv,
+       .stat_fn = vfswrap_stat,
+       .fstat_fn = vfswrap_fstat,
+       .lstat_fn = vfswrap_lstat,
+       .get_alloc_size_fn = vfswrap_get_alloc_size,
+       .unlink_fn = vfswrap_unlink,
+       .chmod_fn = vfswrap_chmod,
+       .fchmod_fn = vfswrap_fchmod,
+       .chown_fn = vfswrap_chown,
+       .fchown_fn = vfswrap_fchown,
+       .lchown_fn = vfswrap_lchown,
+       .chdir_fn = vfswrap_chdir,
+       .getwd_fn = vfswrap_getwd,
+       .ntimes_fn = vfswrap_ntimes,
+       .ftruncate_fn = vfswrap_ftruncate,
+       .fallocate_fn = vfswrap_fallocate,
+       .lock_fn = vfswrap_lock,
+       .kernel_flock_fn = vfswrap_kernel_flock,
+       .linux_setlease_fn = vfswrap_linux_setlease,
+       .getlock_fn = vfswrap_getlock,
+       .symlink_fn = vfswrap_symlink,
+       .readlink_fn = vfswrap_readlink,
+       .link_fn = vfswrap_link,
+       .mknod_fn = vfswrap_mknod,
+       .realpath_fn = vfswrap_realpath,
+       .notify_watch_fn = vfswrap_notify_watch,
+       .chflags_fn = vfswrap_chflags,
+       .file_id_create_fn = vfswrap_file_id_create,
+       .streaminfo_fn = vfswrap_streaminfo,
+       .get_real_filename_fn = vfswrap_get_real_filename,
+       .connectpath_fn = vfswrap_connectpath,
+       .brl_lock_windows_fn = vfswrap_brl_lock_windows,
+       .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
+       .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
+       .strict_lock_fn = vfswrap_strict_lock,
+       .strict_unlock_fn = vfswrap_strict_unlock,
+       .translate_name_fn = vfswrap_translate_name,
+       .fsctl_fn = vfswrap_fsctl,
+       .copy_chunk_send_fn = vfswrap_copy_chunk_send,
+       .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
 
        /* NT ACL operations. */
 
-       .fget_nt_acl = vfswrap_fget_nt_acl,
-       .get_nt_acl = vfswrap_get_nt_acl,
-       .fset_nt_acl = vfswrap_fset_nt_acl,
+       .fget_nt_acl_fn = vfswrap_fget_nt_acl,
+       .get_nt_acl_fn = vfswrap_get_nt_acl,
+       .fset_nt_acl_fn = vfswrap_fset_nt_acl,
+       .audit_file_fn = vfswrap_audit_file,
 
        /* POSIX ACL operations. */
 
-       .chmod_acl = vfswrap_chmod_acl,
-       .fchmod_acl = vfswrap_fchmod_acl,
-
-       .sys_acl_get_entry = vfswrap_sys_acl_get_entry,
-       .sys_acl_get_tag_type = vfswrap_sys_acl_get_tag_type,
-       .sys_acl_get_permset = vfswrap_sys_acl_get_permset,
-       .sys_acl_get_qualifier = vfswrap_sys_acl_get_qualifier,
-       .sys_acl_get_file = vfswrap_sys_acl_get_file,
-       .sys_acl_get_fd = vfswrap_sys_acl_get_fd,
-       .sys_acl_clear_perms = vfswrap_sys_acl_clear_perms,
-       .sys_acl_add_perm = vfswrap_sys_acl_add_perm,
-       .sys_acl_to_text = vfswrap_sys_acl_to_text,
-       .sys_acl_init = vfswrap_sys_acl_init,
-       .sys_acl_create_entry = vfswrap_sys_acl_create_entry,
-       .sys_acl_set_tag_type = vfswrap_sys_acl_set_tag_type,
-       .sys_acl_set_qualifier = vfswrap_sys_acl_set_qualifier,
-       .sys_acl_set_permset = vfswrap_sys_acl_set_permset,
-       .sys_acl_valid = vfswrap_sys_acl_valid,
-       .sys_acl_set_file = vfswrap_sys_acl_set_file,
-       .sys_acl_set_fd = vfswrap_sys_acl_set_fd,
-       .sys_acl_delete_def_file = vfswrap_sys_acl_delete_def_file,
-       .sys_acl_get_perm = vfswrap_sys_acl_get_perm,
-       .sys_acl_free_text = vfswrap_sys_acl_free_text,
-       .sys_acl_free_acl = vfswrap_sys_acl_free_acl,
-       .sys_acl_free_qualifier = vfswrap_sys_acl_free_qualifier,
+       .chmod_acl_fn = vfswrap_chmod_acl,
+       .fchmod_acl_fn = vfswrap_fchmod_acl,
+
+       .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
+       .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
+       .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
+       .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
+       .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
+       .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
+       .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
 
        /* EA operations. */
-       .getxattr = vfswrap_getxattr,
-       .lgetxattr = vfswrap_lgetxattr,
-       .fgetxattr = vfswrap_fgetxattr,
-       .listxattr = vfswrap_listxattr,
-       .llistxattr = vfswrap_llistxattr,
-       .flistxattr = vfswrap_flistxattr,
-       .removexattr = vfswrap_removexattr,
-       .lremovexattr = vfswrap_lremovexattr,
-       .fremovexattr = vfswrap_fremovexattr,
-       .setxattr = vfswrap_setxattr,
-       .lsetxattr = vfswrap_lsetxattr,
-       .fsetxattr = vfswrap_fsetxattr,
+       .getxattr_fn = vfswrap_getxattr,
+       .fgetxattr_fn = vfswrap_fgetxattr,
+       .listxattr_fn = vfswrap_listxattr,
+       .flistxattr_fn = vfswrap_flistxattr,
+       .removexattr_fn = vfswrap_removexattr,
+       .fremovexattr_fn = vfswrap_fremovexattr,
+       .setxattr_fn = vfswrap_setxattr,
+       .fsetxattr_fn = vfswrap_fsetxattr,
 
        /* aio operations */
-       .aio_read = vfswrap_aio_read,
-       .aio_write = vfswrap_aio_write,
-       .aio_return_fn = vfswrap_aio_return,
-       .aio_cancel = vfswrap_aio_cancel,
-       .aio_error_fn = vfswrap_aio_error,
-       .aio_fsync = vfswrap_aio_fsync,
-       .aio_suspend = vfswrap_aio_suspend,
-       .aio_force = vfswrap_aio_force,
+       .aio_force_fn = vfswrap_aio_force,
 
        /* offline operations */
-       .is_offline = vfswrap_is_offline,
-       .set_offline = vfswrap_set_offline
+       .is_offline_fn = vfswrap_is_offline,
+       .set_offline_fn = vfswrap_set_offline,
+
+       /* durable handle operations */
+       .durable_cookie_fn = vfswrap_durable_cookie,
+       .durable_disconnect_fn = vfswrap_durable_disconnect,
+       .durable_reconnect_fn = vfswrap_durable_reconnect,
 };
 
 NTSTATUS vfs_default_init(void);