#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"
be refactored if it becomes more widely used.
******************************************************************/
-#define EXT_DATA_AREA(e) ((uint8 *)(e) + sizeof(struct vfs_fsp_data))
+#define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
files_struct *fsp, size_t ext_size,
ssize_t ret;
if (req && req->unread_bytes) {
- int sockfd = req->sconn->sock;
+ int sockfd = req->xconn->transport.sock;
int old_flags;
SMB_ASSERT(req->unread_bytes == N);
/* VFS_RECVFILE must drain the socket
ssize_t ret;
if (req && req->unread_bytes) {
- int sockfd = req->sconn->sock;
+ int sockfd = req->xconn->transport.sock;
SMB_ASSERT(req->unread_bytes == N);
/* VFS_RECVFILE must drain the socket
* before returning. */
fsp,
offset + total,
N - total);
-#if defined(EWOULDBLOCK)
if (ret == 0 || (ret == -1 &&
- (errno == EAGAIN || errno == EWOULDBLOCK))) {
-#else /* EWOULDBLOCK */
- if (ret == 0 || (ret == -1 && errno == EAGAIN)) {
-#endif /* EWOULDBLOCK */
+ (errno == EAGAIN ||
+ errno == EWOULDBLOCK))) {
int old_flags;
/* Ensure the socket is blocking. */
old_flags = fcntl(sockfd, F_GETFL, 0);
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_KEEP_SIZE, 0, len);
+ ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
+ 0, len);
} else {
ret = 0;
}
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;
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;
}
* 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:
Transfer some data (n bytes) between two file_struct's.
****************************************************************************/
-static ssize_t vfs_read_fn(void *file, void *buf, size_t len)
+static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
{
struct files_struct *fsp = (struct files_struct *)file;
- return SMB_VFS_READ(fsp, buf, len);
+ return SMB_VFS_PREAD(fsp, buf, len, offset);
}
-static ssize_t vfs_write_fn(void *file, const void *buf, size_t len)
+static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
{
struct files_struct *fsp = (struct files_struct *)file;
- return SMB_VFS_WRITE(fsp, buf, len);
+ return SMB_VFS_PWRITE(fsp, buf, len, offset);
}
off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
{
return transfer_file_internal((void *)in, (void *)out, n,
- vfs_read_fn, vfs_write_fn);
+ vfs_pread_fn, vfs_pwrite_fn);
}
/*******************************************************************
struct smb_filename *smb_fname_cwd = NULL;
struct privilege_paths *priv_paths = NULL;
int ret;
+ bool matched;
DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
fname,
}
rootdir_len = strlen(conn_rootdir);
- if (strncmp(conn_rootdir, resolved_name, rootdir_len) != 0) {
+ matched = (strncmp(conn_rootdir, resolved_name, rootdir_len) == 0);
+
+ if (!matched || (resolved_name[rootdir_len] != '/' &&
+ resolved_name[rootdir_len] != '\0')) {
DEBUG(2, ("check_reduced_name_with_privilege: Bad access "
"attempt: %s is a symlink outside the "
"share path\n",
bool allow_symlinks = true;
bool allow_widelinks = false;
- DEBUG(3,("check_reduced_name [%s] [%s]\n", fname, conn->connectpath));
+ DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
resolved_name = SMB_VFS_REALPATH(conn,fname);
if (!allow_widelinks || !allow_symlinks) {
const char *conn_rootdir;
size_t rootdir_len;
+ bool matched;
conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
if (conn_rootdir == NULL) {
}
rootdir_len = strlen(conn_rootdir);
- if (strncmp(conn_rootdir, resolved_name,
- rootdir_len) != 0) {
+ matched = (strncmp(conn_rootdir, resolved_name,
+ rootdir_len) == 0);
+ if (!matched || (resolved_name[rootdir_len] != '/' &&
+ resolved_name[rootdir_len] != '\0')) {
DEBUG(2, ("check_reduced_name: Bad access "
"attempt: %s is a symlink outside the "
"share path\n", fname));
out:
- DEBUG(3,("check_reduced_name: %s reduced to %s\n", fname,
- resolved_name));
+ DBG_INFO("%s reduced to %s\n", fname, resolved_name);
SAFE_FREE(resolved_name);
return NT_STATUS_OK;
}
/**
* XXX: This is temporary and there should be no callers of this once
* smb_filename is plumbed through all path based operations.
+ *
+ * Called when we know stream name parsing has already been done.
*/
-int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname,
+int vfs_stat_smb_basename(struct connection_struct *conn, const char *fname,
SMB_STRUCT_STAT *psbuf)
{
- struct smb_filename *smb_fname;
+ struct smb_filename smb_fname = {
+ .base_name = discard_const_p(char, fname)
+ };
int ret;
- smb_fname = synthetic_smb_fname_split(talloc_tos(), fname, NULL);
- if (smb_fname == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
if (lp_posix_pathnames()) {
- ret = SMB_VFS_LSTAT(conn, smb_fname);
+ ret = SMB_VFS_LSTAT(conn, &smb_fname);
} else {
- ret = SMB_VFS_STAT(conn, smb_fname);
+ ret = SMB_VFS_STAT(conn, &smb_fname);
}
if (ret != -1) {
- *psbuf = smb_fname->st;
+ *psbuf = smb_fname.st;
}
-
- TALLOC_FREE(smb_fname);
- return ret;
-}
-
-/**
- * XXX: This is temporary and there should be no callers of this once
- * smb_filename is plumbed through all path based operations.
- */
-int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
- SMB_STRUCT_STAT *psbuf)
-{
- struct smb_filename *smb_fname;
- int ret;
-
- smb_fname = synthetic_smb_fname_split(talloc_tos(), fname, NULL);
- if (smb_fname == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- ret = SMB_VFS_LSTAT(conn, smb_fname);
- if (ret != -1) {
- *psbuf = smb_fname->st;
- }
-
- TALLOC_FREE(smb_fname);
return ret;
}
int ret;
if(fsp->fh->fd == -1) {
- if (fsp->posix_open) {
+ if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
} else {
ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
}
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,
DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
const char *fname, const char *mask,
- uint32 attributes)
+ uint32_t attributes)
{
VFS_FIND(opendir);
return handle->fns->opendir_fn(handle, fname, mask, attributes);
DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const char *mask,
- uint32 attributes)
+ uint32_t attributes)
{
VFS_FIND(fdopendir);
return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
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,
path = fsp->fsp_name->base_name;
}
- if (fsp->posix_open || as_root) {
+ if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) || as_root) {
ret = SMB_VFS_LCHOWN(fsp->conn,
path,
uid, gid);
}
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);
}
int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
- struct files_struct *fsp, uint32 share_mode,
+ struct files_struct *fsp, uint32_t share_mode,
uint32_t access_mask)
{
VFS_FIND(kernel_flock);
return handle->fns->realpath_fn(handle, path);
}
-NTSTATUS smb_vfs_call_notify_watch(struct vfs_handle_struct *handle,
- struct sys_notify_context *ctx,
- const char *path,
- uint32_t *filter,
- uint32_t *subdir_filter,
- void (*callback)(struct sys_notify_context *ctx,
- void *private_data,
- struct notify_event *ev),
- void *private_data, void *handle_p)
-{
- VFS_FIND(notify_watch);
- return handle->fns->notify_watch_fn(handle, ctx, path,
- filter, subdir_filter, callback,
- private_data, handle_p);
-}
-
int smb_vfs_call_chflags(struct vfs_handle_struct *handle, const char *path,
unsigned int flags)
{
compression_fmt);
}
+NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *service_path,
+ char **base_volume)
+{
+ VFS_FIND(snap_check_path);
+ return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
+ base_volume);
+}
+
+NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *base_volume,
+ time_t *tstamp,
+ bool rw,
+ char **base_path,
+ char **snap_path)
+{
+ VFS_FIND(snap_create);
+ return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
+ rw, base_path, snap_path);
+}
+
+NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ char *base_path,
+ char *snap_path)
+{
+ VFS_FIND(snap_delete);
+ return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
+ snap_path);
+}
+
NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
- uint32 security_info,
+ uint32_t security_info,
TALLOC_CTX *mem_ctx,
struct security_descriptor **ppdesc)
{
NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
const char *name,
- uint32 security_info,
+ uint32_t security_info,
TALLOC_CTX *mem_ctx,
struct security_descriptor **ppdesc)
{
NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
- uint32 security_info_sent,
+ uint32_t security_info_sent,
const struct security_descriptor *psd)
{
VFS_FIND(fset_nt_acl);
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);
+}