#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
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;
"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);
}
-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)
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);
}
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 */
}
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;
}
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;
}
#else /* HAVE_PREAD */
- SMB_OFF_T curr;
+ off_t curr;
int lerrno;
curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
}
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;
}
#else /* HAVE_PWRITE */
- SMB_OFF_T curr;
+ off_t curr;
int lerrno;
curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
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
}
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;
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;
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.
}
#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
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;
}
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;
/* 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;
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;
}
/* 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;
}
if (pst->st_ex_size > len) {
- /* the sys_ftruncate should have worked */
+ /* the ftruncate should have worked */
goto done;
}
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;
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;
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;
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;
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),
* 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
/*
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)) {
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;
}
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;
}
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;
}
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
#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)
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)
{
NTSTATUS status;
char *path;
+ bool offline = false;
if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
return false;
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,
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);