#include "system/filesys.h"
#include "smbd/smbd.h"
#include "smbd/globals.h"
-#include "memcache.h"
+#include "../lib/util/memcache.h"
#include "transfer_file.h"
#include "ntioctl.h"
#include "lib/util/tevent_unix.h"
return (ssize_t)total;
}
-ssize_t vfs_pread_data(files_struct *fsp, char *buf,
- size_t byte_count, off_t offset)
-{
- size_t total=0;
-
- while (total < byte_count)
- {
- ssize_t ret = SMB_VFS_PREAD(fsp, buf + total,
- byte_count - total, offset + total);
-
- if (ret == 0) return total;
- if (ret == -1) {
- if (errno == EINTR)
- continue;
- else
- return -1;
- }
- total += ret;
- }
- return (ssize_t)total;
-}
-
/****************************************************************************
Write data to a fd on the vfs.
****************************************************************************/
ssize_t ret;
if (req && req->unread_bytes) {
+ int sockfd = req->xconn->transport.sock;
+ int old_flags;
SMB_ASSERT(req->unread_bytes == N);
/* VFS_RECVFILE must drain the socket
* before returning. */
req->unread_bytes = 0;
- return SMB_VFS_RECVFILE(req->sconn->sock,
+ /* Ensure the socket is blocking. */
+ old_flags = fcntl(sockfd, F_GETFL, 0);
+ if (set_blocking(sockfd, true) == -1) {
+ return (ssize_t)-1;
+ }
+ ret = SMB_VFS_RECVFILE(sockfd,
fsp,
(off_t)-1,
N);
+ if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
+ return (ssize_t)-1;
+ }
+ return ret;
}
while (total < N) {
ssize_t ret;
if (req && req->unread_bytes) {
+ int sockfd = req->xconn->transport.sock;
SMB_ASSERT(req->unread_bytes == N);
/* VFS_RECVFILE must drain the socket
* before returning. */
req->unread_bytes = 0;
- return SMB_VFS_RECVFILE(req->sconn->sock,
- fsp,
- offset,
- N);
+ /*
+ * Leave the socket non-blocking and
+ * use SMB_VFS_RECVFILE. If it returns
+ * EAGAIN || EWOULDBLOCK temporarily set
+ * the socket blocking and retry
+ * the RECVFILE.
+ */
+ while (total < N) {
+ ret = SMB_VFS_RECVFILE(sockfd,
+ fsp,
+ offset + total,
+ N - total);
+ if (ret == 0 || (ret == -1 &&
+ (errno == EAGAIN ||
+ errno == EWOULDBLOCK))) {
+ int old_flags;
+ /* Ensure the socket is blocking. */
+ old_flags = fcntl(sockfd, F_GETFL, 0);
+ if (set_blocking(sockfd, true) == -1) {
+ return (ssize_t)-1;
+ }
+ ret = SMB_VFS_RECVFILE(sockfd,
+ fsp,
+ offset + total,
+ N - total);
+ if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
+ return (ssize_t)-1;
+ }
+ if (ret == -1) {
+ return (ssize_t)-1;
+ }
+ total += ret;
+ return (ssize_t)total;
+ }
+ /* Any other error case. */
+ if (ret == -1) {
+ return ret;
+ }
+ total += ret;
+ }
+ return (ssize_t)total;
}
while (total < N) {
contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
- flush_write_cache(fsp, SIZECHANGE_FLUSH);
+ flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
if ((ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len)) != -1) {
set_filelen_write_cache(fsp, len);
}
return ret;
}
- if (!lp_strict_allocate(SNUM(fsp->conn)))
- return 0;
-
/* Grow - we need to test if we have enough space. */
contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
- /* See if we have a syscall that will allocate beyond end-of-file
- without changing EOF. */
- ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_KEEP_SIZE, 0, len);
+ if (lp_strict_allocate(SNUM(fsp->conn))) {
+ /* See if we have a syscall that will allocate beyond
+ end-of-file without changing EOF. */
+ ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
+ 0, len);
+ } else {
+ ret = 0;
+ }
contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
return 0;
}
+ if (ret == -1 && errno == ENOSPC) {
+ return -1;
+ }
+
len -= fsp->fsp_name->st.st_ex_size;
len /= 1024; /* Len is now number of 1k blocks needed. */
- space_avail = get_dfree_info(conn, fsp->fsp_name->base_name, false,
+ space_avail = get_dfree_info(conn, fsp->fsp_name->base_name,
&bsize, &dfree, &dsize);
if (space_avail == (uint64_t)-1) {
return -1;
DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
fsp_str_dbg(fsp), (double)len));
- flush_write_cache(fsp, SIZECHANGE_FLUSH);
+ flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
set_filelen_write_cache(fsp, len);
notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
as this is also called from the default SMB_VFS_FTRUNCATE code.
Always extends the file size.
- Returns 0 on success, errno on failure.
+ Returns 0 on success, -1 on failure.
****************************************************************************/
#define SPARSE_BUF_WRITE_SIZE (32*1024)
sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
if (!sparse_buf) {
errno = ENOMEM;
- return ENOMEM;
+ return -1;
}
}
pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
if (pwrite_ret == -1) {
+ int saved_errno = errno;
DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
"%s failed with error %s\n",
- fsp_str_dbg(fsp), strerror(errno)));
- return errno;
+ fsp_str_dbg(fsp), strerror(saved_errno)));
+ errno = saved_errno;
+ return -1;
}
total += pwrite_ret;
}
contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
- flush_write_cache(fsp, SIZECHANGE_FLUSH);
+ flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
offset = fsp->fsp_name->st.st_ex_size;
num_to_write = len - fsp->fsp_name->st.st_ex_size;
* emulation is being done by the libc (like on AIX with JFS1). In that
* case we do our own emulation. fallocate implementations can
* return ENOTSUP or EINVAL in cases like that. */
- ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
- offset, num_to_write);
- if (ret == ENOSPC) {
- errno = ENOSPC;
- ret = -1;
+ ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
+ if (ret == -1 && errno == ENOSPC) {
goto out;
}
if (ret == 0) {
}
ret = vfs_slow_fallocate(fsp, offset, num_to_write);
- if (ret != 0) {
- errno = ret;
- ret = -1;
- }
out:
LastDir = SMB_STRDUP("");
}
- if (strcsequal(path,".")) {
+ if (ISDOT(path)) {
return 0;
}
}
allow_widelinks = lp_widelinks(SNUM(conn));
- allow_symlinks = lp_symlinks(SNUM(conn));
+ allow_symlinks = lp_follow_symlinks(SNUM(conn));
/* Common widelinks and symlinks checks. */
if (!allow_widelinks || !allow_symlinks) {
int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
SMB_STRUCT_STAT *psbuf)
{
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
+ struct smb_filename *smb_fname;
int ret;
- status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
+ smb_fname = synthetic_smb_fname_split(talloc_tos(), fname, NULL);
+ if (smb_fname == NULL) {
+ errno = ENOMEM;
return -1;
}
}
uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
- const char *path, bool small_query,
- uint64_t *bsize, uint64_t *dfree,
- uint64_t *dsize)
+ const char *path, uint64_t *bsize,
+ uint64_t *dfree, uint64_t *dsize)
{
VFS_FIND(disk_free);
- return handle->fns->disk_free_fn(handle, path, small_query, bsize,
- dfree, dsize);
+ return handle->fns->disk_free_fn(handle, path, bsize, dfree, dsize);
}
int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
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)
{
VFS_FIND(create_file);
return handle->fns->create_file_fn(
handle, req, root_dir_fid, smb_fname, access_mask,
share_access, create_disposition, create_options,
- file_attributes, oplock_request, allocation_size,
+ file_attributes, oplock_request, lease, allocation_size,
private_flags, sd, ea_list,
- result, pinfo);
+ result, pinfo, in_context_blobs, out_context_blobs);
}
int smb_vfs_call_close(struct vfs_handle_struct *handle,
}
int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- enum vfs_fallocate_mode mode,
- off_t offset,
- off_t len)
+ struct files_struct *fsp,
+ uint32_t mode,
+ off_t offset,
+ off_t len)
{
VFS_FIND(fallocate);
return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
return handle->fns->copy_chunk_recv_fn(handle, req, copied);
}
+NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct files_struct *fsp,
+ struct smb_filename *smb_fname,
+ uint16_t *_compression_fmt)
+{
+ VFS_FIND(get_compression);
+ return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
+ _compression_fmt);
+}
+
+NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct files_struct *fsp,
+ uint16_t compression_fmt)
+{
+ VFS_FIND(set_compression);
+ return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
+ compression_fmt);
+}
+
NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
uint32 security_info,
old_cookie, mem_ctx, fsp,
new_cookie);
}
+
+NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
+ const struct smb_filename *fname,
+ TALLOC_CTX *mem_ctx,
+ struct readdir_attr_data **attr_data)
+{
+ VFS_FIND(readdir_attr);
+ return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);
+}