#include "lib/util/tevent_unix.h"
#include "lib/asys/asys.h"
#include "lib/util/tevent_ntstatus.h"
+#include "lib/sys_rw.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
if (ret == 0) {
init_stat_ex_from_stat(sbuf,
&st,
- lp_fake_dir_create_times(
+ lp_fake_directory_create_times(
SNUM(handle->conn)));
}
}
return result;
}
+static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
+ const struct smb_filename *fname,
+ TALLOC_CTX *mem_ctx,
+ struct readdir_attr_data **attr_data)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
{
START_PROFILE(syscall_seekdir);
if (lp_inherit_acls(SNUM(handle->conn))
&& parent_dirname(talloc_tos(), path, &parent, NULL)
&& (has_dacl = directory_has_default_acl(handle->conn, parent)))
- mode = (0777 & lp_dir_mask(SNUM(handle->conn)));
+ mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
TALLOC_FREE(parent);
uint32_t create_options,
uint32_t file_attributes,
uint32_t oplock_request,
+ struct smb2_lease *lease,
uint64_t allocation_size,
uint32_t private_flags,
struct security_descriptor *sd,
struct ea_list *ea_list,
files_struct **result,
- int *pinfo)
+ int *pinfo,
+ const struct smb2_create_blobs *in_context_blobs,
+ struct smb2_create_blobs *out_context_blobs)
{
return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
access_mask, share_access,
create_disposition, create_options,
- file_attributes, oplock_request,
+ file_attributes, oplock_request, lease,
allocation_size, private_flags,
sd, ea_list, result,
- pinfo);
+ pinfo, in_context_blobs, out_context_blobs);
}
static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
START_PROFILE_BYTES(syscall_read, n);
result = sys_read(fsp->fh->fd, data, n);
- END_PROFILE(syscall_read);
+ END_PROFILE_BYTES(syscall_read);
return result;
}
#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
START_PROFILE_BYTES(syscall_pread, n);
result = sys_pread(fsp->fh->fd, data, n, offset);
- END_PROFILE(syscall_pread);
+ END_PROFILE_BYTES(syscall_pread);
if (result == -1 && errno == ESPIPE) {
/* Maintain the fiction that pipes can be seeked (sought?) on. */
START_PROFILE_BYTES(syscall_write, n);
result = sys_write(fsp->fh->fd, data, n);
- END_PROFILE(syscall_write);
+ END_PROFILE_BYTES(syscall_write);
return result;
}
#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
START_PROFILE_BYTES(syscall_pwrite, n);
result = sys_pwrite(fsp->fh->fd, data, n, offset);
- END_PROFILE(syscall_pwrite);
+ END_PROFILE_BYTES(syscall_pwrite);
if (result == -1 && errno == ESPIPE) {
/* Maintain the fiction that pipes can be sought on. */
struct tevent_fd *fde,
uint16_t flags, void *p);
-static bool vfswrap_init_asys_ctx(struct smbXsrv_connection *conn)
+static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
{
int ret;
int fd;
struct tevent_req *req;
ssize_t ret;
int err;
+ SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
+ SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
};
static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
if (req == NULL) {
return NULL;
}
- if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
+ if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
tevent_req_oom(req);
return tevent_req_post(req, ev);
}
- state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
+ state->asys_ctx = handle->conn->sconn->asys_ctx;
state->req = req;
+ SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
+ state->profile_bytes, n);
ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
if (ret != 0) {
tevent_req_error(req, ret);
if (req == NULL) {
return NULL;
}
- if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
+ if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
tevent_req_oom(req);
return tevent_req_post(req, ev);
}
- state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
+ state->asys_ctx = handle->conn->sconn->asys_ctx;
state->req = req;
+ SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
+ state->profile_bytes, n);
ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
if (ret != 0) {
tevent_req_error(req, ret);
if (req == NULL) {
return NULL;
}
- if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
+ if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
tevent_req_oom(req);
return tevent_req_post(req, ev);
}
- state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
+ state->asys_ctx = handle->conn->sconn->asys_ctx;
state->req = req;
+ SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
+ state->profile_basic);
ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
if (ret != 0) {
tevent_req_error(req, ret);
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;
+ struct asys_result results[outstanding_aio_calls];
+ int i, ret;
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
+ ret = asys_results(asys_ctx, results, outstanding_aio_calls);
+ if (ret < 0) {
+ DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
+ return;
+ }
- if (res == ECANCELED) {
- return;
- }
+ for (i=0; i<ret; i++) {
+ struct asys_result *result = &results[i];
+ struct tevent_req *req;
+ struct vfswrap_asys_state *state;
- if (res != 0) {
- DEBUG(1, ("asys_result returned %s\n", strerror(res)));
- return;
+ if ((result->ret == -1) && (result->err == ECANCELED)) {
+ continue;
}
- req = talloc_get_type_abort(private_data, struct tevent_req);
+ req = talloc_get_type_abort(result->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;
+ SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
+ SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
+ state->ret = result->ret;
+ state->err = result->err;
tevent_req_defer_callback(req, ev);
tevent_req_done(req);
}
START_PROFILE_BYTES(syscall_sendfile, n);
result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
- END_PROFILE(syscall_sendfile);
+ END_PROFILE_BYTES(syscall_sendfile);
return result;
}
START_PROFILE_BYTES(syscall_recvfile, n);
result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
- END_PROFILE(syscall_recvfile);
+ END_PROFILE_BYTES(syscall_recvfile);
return result;
}
}
result = sys_stat(smb_fname->base_name, &smb_fname->st,
- lp_fake_dir_create_times(SNUM(handle->conn)));
+ lp_fake_directory_create_times(SNUM(handle->conn)));
out:
END_PROFILE(syscall_stat);
return result;
START_PROFILE(syscall_fstat);
result = sys_fstat(fsp->fh->fd,
- sbuf, lp_fake_dir_create_times(SNUM(handle->conn)));
+ sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
END_PROFILE(syscall_fstat);
return result;
}
}
result = sys_lstat(smb_fname->base_name, &smb_fname->st,
- lp_fake_dir_create_times(SNUM(handle->conn)));
+ lp_fake_directory_create_times(SNUM(handle->conn)));
out:
END_PROFILE(syscall_lstat);
return result;
{
const char *in_data = (const char *)_in_data;
char **out_data = (char **)_out_data;
+ NTSTATUS status;
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,
+ smb_fname_str_dbg(fsp->fsp_name), set_sparse,
nt_errstr(status)));
return status;
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;
+ *out_len = MIN(max_out_len, 64);
+
/* Hmmm, will this cause problems if less data asked for? */
return_data = talloc_array(ctx, char, 64);
if (return_data == NULL) {
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);
+ memset(return_data+48, 0, 16);
*out_data = return_data;
return NT_STATUS_OK;
}
* 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;
+ int log_lev = 0;
+ if (errno == 0) {
+ /* broken module didn't set errno on error */
+ status = NT_STATUS_UNSUCCESSFUL;
} else {
- DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n",
- fsp->conn->connectpath));
- return NT_STATUS_UNSUCCESSFUL;
+ status = map_nt_error_from_unix(errno);
+ if (NT_STATUS_EQUAL(status,
+ NT_STATUS_NOT_SUPPORTED)) {
+ log_lev = 5;
+ }
}
+ DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
+ "connectpath %s, failed - %s.\n",
+ fsp->conn->connectpath,
+ nt_errstr(status)));
+ TALLOC_FREE(shadow_data);
+ return status;
}
- labels_data_count = (shadow_data->num_volumes * 2 *
+ labels_data_count = (shadow_data->num_volumes * 2 *
sizeof(SHADOW_COPY_LABEL)) + 2;
if (!labels) {
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,
+ size_t len = 0;
+ status = srvstr_push(cur_pdata, req_flags,
cur_pdata, shadow_data->labels[i],
2 * sizeof(SHADOW_COPY_LABEL),
- STR_UNICODE|STR_TERMINATE);
+ STR_UNICODE|STR_TERMINATE, &len);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(*out_data);
+ TALLOC_FREE(shadow_data);
+ return status;
+ }
cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
}
* 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;
}
default:
- /*
+ /*
* Only print once ... unfortunately there could be lots of
* different FSCTLs that are called.
*/
off_t this_num = MIN(sizeof(vfs_cc_state->buf),
num - vfs_cc_state->copied);
+ if (src_fsp->op == NULL) {
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return tevent_req_post(req, ev);
+ }
init_strict_lock_struct(src_fsp,
src_fsp->op->global->open_persistent_id,
src_off,
src_off += ret;
+ if (dest_fsp->op == NULL) {
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return tevent_req_post(req, ev);
+ }
+
init_strict_lock_struct(dest_fsp,
dest_fsp->op->global->open_persistent_id,
dest_off,
return NT_STATUS_OK;
}
+static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct files_struct *fsp,
+ struct smb_filename *smb_fname,
+ uint16_t *_compression_fmt)
+{
+ return NT_STATUS_INVALID_DEVICE_REQUEST;
+}
+
+static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct files_struct *fsp,
+ uint16_t compression_fmt)
+{
+ return NT_STATUS_INVALID_DEVICE_REQUEST;
+}
+
/********************************************************************
Given a stat buffer return the allocated size on disk, taking into
account sparse files.
#else
#error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
#endif
+ if (result == 0) {
+ /*
+ * Some file systems do not allocate a block for very
+ * small files. But for non-empty file should report a
+ * positive size.
+ */
+
+ uint64_t filesize = get_file_size_stat(sbuf);
+ if (filesize > 0) {
+ result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
+ }
+ }
#else
result = get_file_size_stat(sbuf);
#endif
return ENOTSUP or EINVAL in cases like that. */
ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
pst->st_ex_size, space_to_write);
- if (ret == ENOSPC) {
- errno = ENOSPC;
+ if (ret == -1 && errno == ENOSPC) {
return -1;
}
if (ret == 0) {
return 0;
}
DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
- "error %d. Falling back to slow manual allocation\n", ret));
+ "error %d. Falling back to slow manual allocation\n", errno));
/* available disk space is enough or not? */
space_avail = get_dfree_info(fsp->conn,
/* Write out the real space on disk. */
ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
if (ret != 0) {
- errno = ret;
- ret = -1;
+ return -1;
}
return 0;
START_PROFILE(syscall_fallocate);
if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
result = sys_posix_fallocate(fsp->fh->fd, offset, len);
+ /*
+ * posix_fallocate returns 0 on success, errno on error
+ * and doesn't set errno. Make it behave like fallocate()
+ * which returns -1, and sets errno on failure.
+ */
+ if (result != 0) {
+ errno = result;
+ result = -1;
+ }
} else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
result = sys_fallocate(fsp->fh->fd, mode, offset, len);
} else {
*/
#ifdef HAVE_INOTIFY
if (lp_kernel_change_notify(vfs_handle->conn->params)) {
+ if (!lp_parm_bool(-1, "notify", "inotify", True)) {
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
+ }
return inotify_watch(ctx, path, filter, subdir_filter,
callback, private_data, handle);
}
static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
struct byte_range_lock *br_lck,
struct lock_struct *plock,
- bool blocking_lock,
- struct blocking_lock_record *blr)
+ bool blocking_lock)
{
SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
struct byte_range_lock *br_lck,
- struct lock_struct *plock,
- struct blocking_lock_record *blr)
+ struct lock_struct *plock)
{
SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
.opendir_fn = vfswrap_opendir,
.fdopendir_fn = vfswrap_fdopendir,
.readdir_fn = vfswrap_readdir,
+ .readdir_attr_fn = vfswrap_readdir_attr,
.seekdir_fn = vfswrap_seekdir,
.telldir_fn = vfswrap_telldir,
.rewind_dir_fn = vfswrap_rewinddir,
.fsctl_fn = vfswrap_fsctl,
.copy_chunk_send_fn = vfswrap_copy_chunk_send,
.copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
+ .get_compression_fn = vfswrap_get_compression,
+ .set_compression_fn = vfswrap_set_compression,
/* NT ACL operations. */