FSCTL_GET_SHADOW_COPY_DATA: Don't return 4 extra bytes at end
[samba.git] / source3 / modules / vfs_default.c
index 4d06a10f42607a58cc4ff91004c87cff8796cf87..67050fa8aceda2c1b2331aa24f57f7c5c288e174 100644 (file)
 #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"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
@@ -104,15 +111,15 @@ 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;
+       struct vfs_statvfs_struct statbuf;
        NTSTATUS status;
-       int ret = -1;
+       int ret;
 
-#if defined(DARWINOS)
-       struct vfs_statvfs_struct statbuf;
        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;
 
@@ -156,31 +163,206 @@ 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_DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
+static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
                        files_struct *fsp,
                        const char *mask,
                        uint32 attr)
 {
-       SMB_STRUCT_DIR *result;
+       DIR *result;
 
        START_PROFILE(syscall_fdopendir);
        result = sys_fdopendir(fsp->fh->fd);
@@ -189,14 +371,14 @@ static SMB_STRUCT_DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
 }
 
 
-static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle,
-                                         SMB_STRUCT_DIR *dirp,
+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);
+       result = readdir(dirp);
        /* Default Posix readdir() does not give us stat info.
         * Set to invalid to indicate we didn't return this info. */
        if (sbuf)
@@ -205,26 +387,26 @@ static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle,
        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);
 }
 
@@ -272,18 +454,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 */
 }
@@ -303,7 +485,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;
@@ -356,7 +538,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;
 
@@ -372,7 +554,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);
@@ -410,7 +592,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;
 
@@ -425,7 +607,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);
@@ -448,15 +630,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)
+{
+       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)
 {
-       SMB_OFF_T result = 0;
+       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
@@ -475,7 +871,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;
 
@@ -488,7 +884,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;
@@ -591,6 +987,342 @@ static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
        return NT_STATUS_NONE_MAPPED;
 }
 
+/*
+ * 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:
+       {
+               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)));
+
+               return status;
+       }
+
+       case FSCTL_CREATE_OR_GET_OBJECT_ID:
+       {
+               unsigned char objid[16];
+               char *return_data = NULL;
+
+               /* This should return the object-id on this file.
+                * I think I'll make this be the inode+dev. JRA.
+                */
+
+               DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
+                         fsp_fnum_dbg(fsp)));
+
+               *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;
+               }
+
+               /* 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;
+       }
+
+       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;
+       }
+
+       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;
+       }
+
+       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;
+               }
+
+               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_zero_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);
+
+               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;
+       }
+
+       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;
+}
+
 /********************************************************************
  Given a stat buffer return the allocated size on disk, taking into
  account sparse files.
@@ -609,7 +1341,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
@@ -748,12 +1493,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;
 }
@@ -851,9 +1596,9 @@ 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_OFF_T space_to_write;
+       off_t space_to_write;
        uint64_t space_avail;
        uint64_t bsize,dfree,dsize;
        int ret;
@@ -876,7 +1621,7 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
 
        /* Shrink - just ftruncate. */
        if (pst->st_ex_size > len)
-               return sys_ftruncate(fsp->fh->fd, len);
+               return ftruncate(fsp->fh->fd, len);
 
        space_to_write = len - pst->st_ex_size;
 
@@ -918,7 +1663,7 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
        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 *pst;
@@ -934,12 +1679,12 @@ static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_O
        }
 
        /* 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;
 
@@ -970,7 +1715,7 @@ static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_O
        }
 
        if (pst->st_ex_size > len) {
-               /* the sys_ftruncate should have worked */
+               /* the ftruncate should have worked */
                goto done;
        }
 
@@ -989,8 +1734,8 @@ static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_O
 static int vfswrap_fallocate(vfs_handle_struct *handle,
                        files_struct *fsp,
                        enum vfs_fallocate_mode mode,
-                       SMB_OFF_T offset,
-                       SMB_OFF_T len)
+                       off_t offset,
+                       off_t len)
 {
        int result;
 
@@ -1007,7 +1752,7 @@ static int vfswrap_fallocate(vfs_handle_struct *handle,
        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 bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
 {
        bool result;
 
@@ -1026,7 +1771,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;
 
@@ -1044,11 +1789,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;
@@ -1122,7 +1862,9 @@ static char *vfswrap_realpath(vfs_handle_struct *handle,  const char *path)
 
 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),
@@ -1137,8 +1879,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
        /*
@@ -1182,8 +1925,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)) {
@@ -1218,25 +1960,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;
 }
 
@@ -1318,12 +2056,14 @@ 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,
+                                   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;
 }
@@ -1331,12 +2071,14 @@ static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
                                   const char *name,
                                   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;
 }
@@ -1351,6 +2093,15 @@ static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp
        return result;
 }
 
+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
@@ -1381,79 +2132,39 @@ 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)
+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_permset(entry_d, permset_p);
+       return sys_acl_get_file(handle, path_p, type, mem_ctx);
 }
 
-static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d)
+static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
+                                       files_struct *fsp,
+                                       TALLOC_CTX *mem_ctx)
 {
-       return sys_acl_get_qualifier(entry_d);
+       return sys_acl_get_fd(handle, fsp, mem_ctx);
 }
 
-static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,  const char *path_p, SMB_ACL_TYPE_T type)
+static int vfswrap_sys_acl_blob_get_file(vfs_handle_struct *handle,
+                                        const char *path_p,
+                                        TALLOC_CTX *mem_ctx,
+                                        char **blob_description,
+                                        DATA_BLOB *blob)
 {
-       return sys_acl_get_file(handle, path_p, type);
-}
-
-static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
-{
-       return sys_acl_get_fd(handle, fsp);
-}
-
-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);
+       errno = ENOSYS;
+       return -1;
 }
 
-static int vfswrap_sys_acl_valid(vfs_handle_struct *handle,  SMB_ACL_T theacl )
+static int vfswrap_sys_acl_blob_get_fd(vfs_handle_struct *handle,
+                                      files_struct *fsp,
+                                      TALLOC_CTX *mem_ctx,
+                                      char **blob_description,
+                                      DATA_BLOB *blob)
 {
-       return sys_acl_valid(theacl );
+       errno = ENOSYS;
+       return -1;
 }
 
 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,  const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
@@ -1471,143 +2182,48 @@ static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,  const cha
        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);
-}
-
-static 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);
 }
 
 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)
@@ -1621,6 +2237,7 @@ static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
 {
        NTSTATUS status;
        char *path;
+       bool offline = false;
 
         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
                return false;
@@ -1639,7 +2256,11 @@ static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
                 return false;
         }
 
-       return (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
+       offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
+
+       TALLOC_FREE(path);
+
+       return offline;
 }
 
 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
@@ -1652,143 +2273,162 @@ static int vfswrap_set_offline(struct vfs_handle_struct *handle,
        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,
-       .fdopendir = vfswrap_fdopendir,
-       .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_fn = vfswrap_open,
-       .create_file = vfswrap_create_file,
+       .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,
-       .fallocate = vfswrap_fallocate,
-       .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,
 
        /* 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 = vfswrap_sys_acl_blob_get_file,
+       .sys_acl_blob_get_fd_fn = vfswrap_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);