X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Fsmbd%2Fvfs.c;h=bed3d2c1554b65fa251de78a054b799695844e76;hb=6ae2d86b9ccc0ebe73dc911a1d5f06bd53613acf;hp=de0cc97205697487630400d24697e8a39c6e02ef;hpb=4e6934ec6c163ad6fd9c317b5a7dd7775b0dc83f;p=sfrench%2Fsamba-autobuild%2F.git diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index de0cc972056..bed3d2c1554 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -27,7 +27,7 @@ #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" @@ -133,7 +133,7 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object) } if(!backends) { - static_init_vfs; + static_init_vfs(NULL); } DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object)); @@ -222,7 +222,7 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object) 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, @@ -316,6 +316,36 @@ void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp) #undef EXT_DATA_AREA +/* + * Ensure this module catches all VFS functions. + */ +#ifdef DEVELOPER +void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns, + const char *module) +{ + bool missing_fn = false; + unsigned int idx; + const uintptr_t *end = (const uintptr_t *)(fns + 1); + + for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) { + if (*((const uintptr_t *)fns + idx) == 0) { + DBG_ERR("VFS function at index %d not implemented " + "in module %s\n", idx, module); + missing_fn = true; + } + } + + if (missing_fn) { + smb_panic("Required VFS function not implemented in module.\n"); + } +} +#else +void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns, + const char *module) +{ +} +#endif + /***************************************************************** Generic VFS init. ******************************************************************/ @@ -393,28 +423,6 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) 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. ****************************************************************************/ @@ -428,7 +436,7 @@ ssize_t vfs_write_data(struct smb_request *req, 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 @@ -472,25 +480,52 @@ ssize_t vfs_pwrite_data(struct smb_request *req, ssize_t ret; if (req && req->unread_bytes) { - int sockfd = req->sconn->sock; - int old_flags; + int sockfd = req->xconn->transport.sock; SMB_ASSERT(req->unread_bytes == N); /* VFS_RECVFILE must drain the socket * before returning. */ req->unread_bytes = 0; - /* 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, - N); - if (fcntl(sockfd, F_SETFL, old_flags) == -1) { - return (ssize_t)-1; + /* + * 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 ret; + return (ssize_t)total; } while (total < N) { @@ -568,7 +603,8 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t 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_KEEP_SIZE, 0, len); + ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE, + 0, len); } else { ret = 0; } @@ -581,10 +617,14 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) 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, - &bsize, &dfree, &dsize); + space_avail = + get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize); if (space_avail == (uint64_t)-1) { return -1; } @@ -635,7 +675,7 @@ int vfs_set_filelen(files_struct *fsp, off_t len) 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) @@ -649,7 +689,7 @@ int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len) sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE); if (!sparse_buf) { errno = ENOMEM; - return ENOMEM; + return -1; } } @@ -658,10 +698,12 @@ int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len) 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; } @@ -717,11 +759,8 @@ int vfs_fill_sparse(files_struct *fsp, off_t len) * 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) { @@ -732,10 +771,6 @@ int vfs_fill_sparse(files_struct *fsp, off_t len) } ret = vfs_slow_fallocate(fsp, offset, num_to_write); - if (ret != 0) { - errno = ret; - ret = -1; - } out: @@ -751,24 +786,24 @@ int vfs_fill_sparse(files_struct *fsp, off_t len) 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); } /******************************************************************* @@ -828,7 +863,7 @@ int vfs_ChDir(connection_struct *conn, const char *path) LastDir = SMB_STRDUP(""); } - if (strcsequal(path,".")) { + if (ISDOT(path)) { return 0; } @@ -871,7 +906,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) goto nocache; } - smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL); + smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0); if (smb_fname_dot == NULL) { errno = ENOMEM; goto out; @@ -899,7 +934,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) && (cache_value.data[cache_value.length-1] == '\0')); smb_fname_full = synthetic_smb_fname(ctx, (char *)cache_value.data, - NULL, NULL); + NULL, NULL, 0); if (smb_fname_full == NULL) { errno = ENOMEM; goto out; @@ -1039,7 +1074,7 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn, resolved_name)); /* Now check the stat value is the same. */ - smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL); + smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0); if (smb_fname_cwd == NULL) { status = NT_STATUS_NO_MEMORY; goto err; @@ -1071,15 +1106,32 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn, } rootdir_len = strlen(conn_rootdir); - if (strncmp(conn_rootdir, resolved_name, rootdir_len) != 0) { - DEBUG(2, ("check_reduced_name_with_privilege: Bad access " - "attempt: %s is a symlink outside the " - "share path\n", - dir_name)); - DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir)); - DEBUGADD(2, ("resolved_name=%s\n", resolved_name)); - status = NT_STATUS_ACCESS_DENIED; - goto err; + + /* + * In the case of rootdir_len == 1, we know that conn_rootdir is + * "/", and we also know that resolved_name starts with a slash. + * So, in this corner case, resolved_name is automatically a + * sub-directory of the conn_rootdir. Thus we can skip the string + * comparison and the next character checks (which are even + * wrong in this case). + */ + if (rootdir_len != 1) { + bool matched; + + 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", + dir_name)); + DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir)); + DEBUGADD(2, ("resolved_name=%s\n", resolved_name)); + status = NT_STATUS_ACCESS_DENIED; + goto err; + } } /* Now ensure that the last component either doesn't @@ -1127,15 +1179,24 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn, /******************************************************************* Reduce a file name, removing .. elements and checking that it is below dir in the heirachy. This uses realpath. + + If cwd_name == NULL then fname is a client given path relative + to the root path of the share. + + If cwd_name != NULL then fname is a client given path relative + to cwd_name. cwd_name is relative to the root path of the share. ********************************************************************/ -NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) +NTSTATUS check_reduced_name(connection_struct *conn, + const char *cwd_name, + const char *fname) { char *resolved_name = NULL; + char *new_fname = NULL; 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); @@ -1205,7 +1266,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) } 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) { @@ -1221,15 +1282,33 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) } rootdir_len = strlen(conn_rootdir); - if (strncmp(conn_rootdir, resolved_name, - rootdir_len) != 0) { - DEBUG(2, ("check_reduced_name: Bad access " - "attempt: %s is a symlink outside the " - "share path\n", fname)); - DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir)); - DEBUGADD(2, ("resolved_name=%s\n", resolved_name)); - SAFE_FREE(resolved_name); - return NT_STATUS_ACCESS_DENIED; + + /* + * In the case of rootdir_len == 1, we know that + * conn_rootdir is "/", and we also know that + * resolved_name starts with a slash. So, in this + * corner case, resolved_name is automatically a + * sub-directory of the conn_rootdir. Thus we can skip + * the string comparison and the next character checks + * (which are even wrong in this case). + */ + if (rootdir_len != 1) { + bool matched; + + 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)); + DEBUGADD(2, ("conn_rootdir =%s\n", + conn_rootdir)); + DEBUGADD(2, ("resolved_name=%s\n", + resolved_name)); + SAFE_FREE(resolved_name); + return NT_STATUS_ACCESS_DENIED; + } } /* Extra checks if all symlinks are disallowed. */ @@ -1237,8 +1316,11 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) /* fname can't have changed in resolved_path. */ const char *p = &resolved_name[rootdir_len]; - /* *p can be '\0' if fname was "." */ - if (*p == '\0' && ISDOT(fname)) { + /* + * UNIX filesystem semantics, names consisting + * only of "." or ".." CANNOT be symlinks. + */ + if (ISDOT(fname) || ISDOTDOT(fname)) { goto out; } @@ -1252,11 +1334,32 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) } p++; + + /* + * If cwd_name is present and not ".", + * then fname is relative to that, not + * the root of the share. Make sure the + * path we check is the one the client + * sent (cwd_name+fname). + */ + if (cwd_name != NULL && !ISDOT(cwd_name)) { + new_fname = talloc_asprintf(talloc_tos(), + "%s/%s", + cwd_name, + fname); + if (new_fname == NULL) { + SAFE_FREE(resolved_name); + return NT_STATUS_NO_MEMORY; + } + fname = new_fname; + } + if (strcmp(fname, p)!=0) { DEBUG(2, ("check_reduced_name: Bad access " "attempt: %s is a symlink to %s\n", fname, p)); SAFE_FREE(resolved_name); + TALLOC_FREE(new_fname); return NT_STATUS_ACCESS_DENIED; } } @@ -1264,64 +1367,37 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *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); + TALLOC_FREE(new_fname); 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, - 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; - } - - if (lp_posix_pathnames()) { - ret = SMB_VFS_LSTAT(conn, smb_fname); - } else { - ret = SMB_VFS_STAT(conn, smb_fname); - } - - if (ret != -1) { - *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, +int vfs_stat_smb_basename(struct connection_struct *conn, + const struct smb_filename *smb_fname_in, SMB_STRUCT_STAT *psbuf) { - struct smb_filename *smb_fname; + struct smb_filename smb_fname = { + .base_name = discard_const_p(char, smb_fname_in->base_name), + .flags = smb_fname_in->flags + }; int ret; - smb_fname = synthetic_smb_fname_split(talloc_tos(), fname, NULL); - if (smb_fname == NULL) { - errno = ENOMEM; - return -1; + if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) { + ret = SMB_VFS_LSTAT(conn, &smb_fname); + } else { + ret = SMB_VFS_STAT(conn, &smb_fname); } - ret = SMB_VFS_LSTAT(conn, smb_fname); if (ret != -1) { - *psbuf = smb_fname->st; + *psbuf = smb_fname.st; } - - TALLOC_FREE(smb_fname); return ret; } @@ -1334,7 +1410,7 @@ NTSTATUS vfs_stat_fsp(files_struct *fsp) 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); @@ -1355,14 +1431,19 @@ NTSTATUS vfs_stat_fsp(files_struct *fsp) */ NTSTATUS vfs_streaminfo(connection_struct *conn, struct files_struct *fsp, - const char *fname, + const struct smb_filename *smb_fname, TALLOC_CTX *mem_ctx, unsigned int *num_streams, struct stream_struct **streams) { *num_streams = 0; *streams = NULL; - return SMB_VFS_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams); + return SMB_VFS_STREAMINFO(conn, + fsp, + smb_fname, + mem_ctx, + num_streams, + streams); } /* @@ -1387,21 +1468,24 @@ void smb_vfs_call_disconnect(struct vfs_handle_struct *handle) } uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle, - const char *path, bool small_query, - uint64_t *bsize, uint64_t *dfree, + const struct smb_filename *smb_fname, + 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, smb_fname, + bsize, dfree, dsize); } int smb_vfs_call_get_quota(struct vfs_handle_struct *handle, - enum SMB_QUOTA_TYPE qtype, unid_t id, - SMB_DISK_QUOTA *qt) + const struct smb_filename *smb_fname, + enum SMB_QUOTA_TYPE qtype, + unid_t id, + SMB_DISK_QUOTA *qt) { VFS_FIND(get_quota); - return handle->fns->get_quota_fn(handle, qtype, id, qt); + return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt); } int smb_vfs_call_set_quota(struct vfs_handle_struct *handle, @@ -1422,11 +1506,12 @@ int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle, shadow_copy_data, labels); } -int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, const char *path, - struct vfs_statvfs_struct *statbuf) +int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + struct vfs_statvfs_struct *statbuf) { VFS_FIND(statvfs); - return handle->fns->statvfs_fn(handle, path, statbuf); + return handle->fns->statvfs_fn(handle, smb_fname, statbuf); } uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle, @@ -1444,17 +1529,18 @@ NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle, } DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle, - const char *fname, const char *mask, - uint32 attributes) + const struct smb_filename *smb_fname, + const char *mask, + uint32_t attributes) { VFS_FIND(opendir); - return handle->fns->opendir_fn(handle, fname, mask, attributes); + return handle->fns->opendir_fn(handle, smb_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); @@ -1489,17 +1575,19 @@ void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle, handle->fns->rewind_dir_fn(handle, dirp); } -int smb_vfs_call_mkdir(struct vfs_handle_struct *handle, const char *path, - mode_t mode) +int smb_vfs_call_mkdir(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + mode_t mode) { VFS_FIND(mkdir); - return handle->fns->mkdir_fn(handle, path, mode); + return handle->fns->mkdir_fn(handle, smb_fname, mode); } -int smb_vfs_call_rmdir(struct vfs_handle_struct *handle, const char *path) +int smb_vfs_call_rmdir(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { VFS_FIND(rmdir); - return handle->fns->rmdir_fn(handle, path); + return handle->fns->rmdir_fn(handle, smb_fname); } int smb_vfs_call_closedir(struct vfs_handle_struct *handle, @@ -1534,20 +1622,23 @@ NTSTATUS smb_vfs_call_create_file(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, @@ -1573,8 +1664,9 @@ ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle, } struct smb_vfs_call_pread_state { - ssize_t (*recv_fn)(struct tevent_req *req, int *err); + ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state); ssize_t retval; + struct vfs_aio_state vfs_aio_state; }; static void smb_vfs_call_pread_done(struct tevent_req *subreq); @@ -1612,27 +1704,26 @@ static void smb_vfs_call_pread_done(struct tevent_req *subreq) subreq, struct tevent_req); struct smb_vfs_call_pread_state *state = tevent_req_data( req, struct smb_vfs_call_pread_state); - int err; - state->retval = state->recv_fn(subreq, &err); + state->retval = state->recv_fn(subreq, &state->vfs_aio_state); TALLOC_FREE(subreq); if (state->retval == -1) { - tevent_req_error(req, err); + tevent_req_error(req, state->vfs_aio_state.error); return; } tevent_req_done(req); } -ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req, int *perrno) +ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req, + struct vfs_aio_state *vfs_aio_state) { struct smb_vfs_call_pread_state *state = tevent_req_data( req, struct smb_vfs_call_pread_state); - int err; - if (tevent_req_is_unix_error(req, &err)) { - *perrno = err; + if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { return -1; } + *vfs_aio_state = state->vfs_aio_state; return state->retval; } @@ -1653,8 +1744,9 @@ ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle, } struct smb_vfs_call_pwrite_state { - ssize_t (*recv_fn)(struct tevent_req *req, int *err); + ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state); ssize_t retval; + struct vfs_aio_state vfs_aio_state; }; static void smb_vfs_call_pwrite_done(struct tevent_req *subreq); @@ -1692,27 +1784,26 @@ static void smb_vfs_call_pwrite_done(struct tevent_req *subreq) subreq, struct tevent_req); struct smb_vfs_call_pwrite_state *state = tevent_req_data( req, struct smb_vfs_call_pwrite_state); - int err; - state->retval = state->recv_fn(subreq, &err); + state->retval = state->recv_fn(subreq, &state->vfs_aio_state); TALLOC_FREE(subreq); if (state->retval == -1) { - tevent_req_error(req, err); + tevent_req_error(req, state->vfs_aio_state.error); return; } tevent_req_done(req); } -ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req, int *perrno) +ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req, + struct vfs_aio_state *vfs_aio_state) { struct smb_vfs_call_pwrite_state *state = tevent_req_data( req, struct smb_vfs_call_pwrite_state); - int err; - if (tevent_req_is_unix_error(req, &err)) { - *perrno = err; + if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { return -1; } + *vfs_aio_state = state->vfs_aio_state; return state->retval; } @@ -1757,8 +1848,9 @@ int smb_vfs_call_fsync(struct vfs_handle_struct *handle, } struct smb_vfs_call_fsync_state { - int (*recv_fn)(struct tevent_req *req, int *err); + int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state); int retval; + struct vfs_aio_state vfs_aio_state; }; static void smb_vfs_call_fsync_done(struct tevent_req *subreq); @@ -1793,27 +1885,25 @@ static void smb_vfs_call_fsync_done(struct tevent_req *subreq) subreq, struct tevent_req); struct smb_vfs_call_fsync_state *state = tevent_req_data( req, struct smb_vfs_call_fsync_state); - int err; - state->retval = state->recv_fn(subreq, &err); + state->retval = state->recv_fn(subreq, &state->vfs_aio_state); TALLOC_FREE(subreq); if (state->retval == -1) { - tevent_req_error(req, err); + tevent_req_error(req, state->vfs_aio_state.error); return; } tevent_req_done(req); } -int SMB_VFS_FSYNC_RECV(struct tevent_req *req, int *perrno) +int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state) { struct smb_vfs_call_fsync_state *state = tevent_req_data( req, struct smb_vfs_call_fsync_state); - int err; - if (tevent_req_is_unix_error(req, &err)) { - *perrno = err; + if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { return -1; } + *vfs_aio_state = state->vfs_aio_state; return state->retval; } @@ -1854,11 +1944,12 @@ int smb_vfs_call_unlink(struct vfs_handle_struct *handle, return handle->fns->unlink_fn(handle, smb_fname); } -int smb_vfs_call_chmod(struct vfs_handle_struct *handle, const char *path, - mode_t mode) +int smb_vfs_call_chmod(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + mode_t mode) { VFS_FIND(chmod); - return handle->fns->chmod_fn(handle, path, mode); + return handle->fns->chmod_fn(handle, smb_fname, mode); } int smb_vfs_call_fchmod(struct vfs_handle_struct *handle, @@ -1868,11 +1959,13 @@ int smb_vfs_call_fchmod(struct vfs_handle_struct *handle, return handle->fns->fchmod_fn(handle, fsp, mode); } -int smb_vfs_call_chown(struct vfs_handle_struct *handle, const char *path, - uid_t uid, gid_t gid) +int smb_vfs_call_chown(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + uid_t uid, + gid_t gid) { VFS_FIND(chown); - return handle->fns->chown_fn(handle, path, uid, gid); + return handle->fns->chown_fn(handle, smb_fname, uid, gid); } int smb_vfs_call_fchown(struct vfs_handle_struct *handle, @@ -1882,20 +1975,19 @@ int smb_vfs_call_fchown(struct vfs_handle_struct *handle, return handle->fns->fchown_fn(handle, fsp, uid, gid); } -int smb_vfs_call_lchown(struct vfs_handle_struct *handle, const char *path, - uid_t uid, gid_t gid) +int smb_vfs_call_lchown(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + uid_t uid, + gid_t gid) { VFS_FIND(lchown); - return handle->fns->lchown_fn(handle, path, uid, gid); + return handle->fns->lchown_fn(handle, smb_fname, uid, gid); } NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid) { int ret; bool as_root = false; - const char *path; - char *saved_dir = NULL; - char *parent_dir = NULL; NTSTATUS status; if (fsp->fh->fd != -1) { @@ -1918,8 +2010,10 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid) * and always act using lchown to ensure we * don't deref any symbolic links. */ + char *saved_dir = NULL; + char *parent_dir = NULL; const char *final_component = NULL; - struct smb_filename local_fname; + struct smb_filename *local_smb_fname = NULL; saved_dir = vfs_GetWd(talloc_tos(),fsp->conn); if (!saved_dir) { @@ -1943,33 +2037,57 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid) return map_nt_error_from_unix(errno); } - ZERO_STRUCT(local_fname); - local_fname.base_name = discard_const_p(char, final_component); + local_smb_fname = synthetic_smb_fname(talloc_tos(), + final_component, + NULL, + NULL, + fsp->fsp_name->flags); + if (local_smb_fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } /* Must use lstat here. */ - ret = SMB_VFS_LSTAT(fsp->conn, &local_fname); + ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname); if (ret == -1) { status = map_nt_error_from_unix(errno); goto out; } /* Ensure it matches the fsp stat. */ - if (!check_same_stat(&local_fname.st, &fsp->fsp_name->st)) { + if (!check_same_stat(&local_smb_fname->st, + &fsp->fsp_name->st)) { status = NT_STATUS_ACCESS_DENIED; goto out; } - path = final_component; - } else { - path = fsp->fsp_name->base_name; - } - if (fsp->posix_open || as_root) { ret = SMB_VFS_LCHOWN(fsp->conn, - path, + local_smb_fname, + uid, gid); + + if (ret == 0) { + status = NT_STATUS_OK; + } else { + status = map_nt_error_from_unix(errno); + } + + out: + + vfs_ChDir(fsp->conn,saved_dir); + TALLOC_FREE(local_smb_fname); + TALLOC_FREE(saved_dir); + TALLOC_FREE(parent_dir); + + return status; + } + + if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { + ret = SMB_VFS_LCHOWN(fsp->conn, + fsp->fsp_name, uid, gid); } else { ret = SMB_VFS_CHOWN(fsp->conn, - path, + fsp->fsp_name, uid, gid); } @@ -1978,14 +2096,6 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid) } else { status = map_nt_error_from_unix(errno); } - - out: - - if (as_root) { - vfs_ChDir(fsp->conn,saved_dir); - TALLOC_FREE(saved_dir); - TALLOC_FREE(parent_dir); - } return status; } @@ -2017,17 +2127,17 @@ int smb_vfs_call_ftruncate(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); } 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); @@ -2050,24 +2160,29 @@ int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath, } int smb_vfs_call_readlink(struct vfs_handle_struct *handle, - const char *path, char *buf, size_t bufsiz) + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { VFS_FIND(readlink); - return handle->fns->readlink_fn(handle, path, buf, bufsiz); + return handle->fns->readlink_fn(handle, smb_fname, buf, bufsiz); } -int smb_vfs_call_link(struct vfs_handle_struct *handle, const char *oldpath, - const char *newpath) +int smb_vfs_call_link(struct vfs_handle_struct *handle, + const struct smb_filename *old_smb_fname, + const struct smb_filename *new_smb_fname) { VFS_FIND(link); - return handle->fns->link_fn(handle, oldpath, newpath); + return handle->fns->link_fn(handle, old_smb_fname, new_smb_fname); } -int smb_vfs_call_mknod(struct vfs_handle_struct *handle, const char *path, - mode_t mode, SMB_DEV_T dev) +int smb_vfs_call_mknod(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + mode_t mode, + SMB_DEV_T dev) { VFS_FIND(mknod); - return handle->fns->mknod_fn(handle, path, mode, dev); + return handle->fns->mknod_fn(handle, smb_fname, mode, dev); } char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path) @@ -2076,27 +2191,12 @@ char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path) 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) +int smb_vfs_call_chflags(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + unsigned int flags) { VFS_FIND(chflags); - return handle->fns->chflags_fn(handle, path, flags); + return handle->fns->chflags_fn(handle, smb_fname, flags); } struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle, @@ -2108,13 +2208,13 @@ struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle, NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle, struct files_struct *fsp, - const char *fname, + const struct smb_filename *smb_fname, TALLOC_CTX *mem_ctx, unsigned int *num_streams, struct stream_struct **streams) { VFS_FIND(streaminfo); - return handle->fns->streaminfo_fn(handle, fsp, fname, mem_ctx, + return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx, num_streams, streams); } @@ -2178,6 +2278,38 @@ NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle, out_len); } +NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle, + struct smb_filename *smb_fname, + uint32_t *dosmode) +{ + VFS_FIND(get_dos_attributes); + return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode); +} + +NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle, + struct files_struct *fsp, + uint32_t *dosmode) +{ + VFS_FIND(fget_dos_attributes); + return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode); +} + +NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + uint32_t dosmode) +{ + VFS_FIND(set_dos_attributes); + return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode); +} + +NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle, + struct files_struct *fsp, + uint32_t dosmode) +{ + VFS_FIND(set_dos_attributes); + return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode); +} + struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -2185,11 +2317,13 @@ struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle off_t src_off, struct files_struct *dest_fsp, off_t dest_off, - off_t num) + off_t num, + uint32_t flags) { VFS_FIND(copy_chunk_send); return handle->fns->copy_chunk_send_fn(handle, mem_ctx, ev, src_fsp, - src_off, dest_fsp, dest_off, num); + src_off, dest_fsp, dest_off, num, + flags); } NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle, @@ -2200,9 +2334,63 @@ NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle, 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_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) { @@ -2212,18 +2400,22 @@ NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle, } NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle, - const char *name, - uint32 security_info, + const struct smb_filename *smb_fname, + uint32_t security_info, TALLOC_CTX *mem_ctx, struct security_descriptor **ppdesc) { VFS_FIND(get_nt_acl); - return handle->fns->get_nt_acl_fn(handle, name, security_info, mem_ctx, ppdesc); + return handle->fns->get_nt_acl_fn(handle, + smb_fname, + security_info, + mem_ctx, + 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); @@ -2245,11 +2437,12 @@ NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle, access_denied); } -int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle, const char *name, - mode_t mode) +int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + mode_t mode) { VFS_FIND(chmod_acl); - return handle->fns->chmod_acl_fn(handle, name, mode); + return handle->fns->chmod_acl_fn(handle, smb_fname, mode); } int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle, @@ -2260,12 +2453,12 @@ int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle, } SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle, - const char *path_p, + const struct smb_filename *smb_fname, SMB_ACL_TYPE_T type, TALLOC_CTX *mem_ctx) { VFS_FIND(sys_acl_get_file); - return handle->fns->sys_acl_get_file_fn(handle, path_p, type, mem_ctx); + return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx); } SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle, @@ -2277,13 +2470,14 @@ SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle, } int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle, - const char *path_p, - TALLOC_CTX *mem_ctx, - char **blob_description, - DATA_BLOB *blob) + const struct smb_filename *smb_fname, + TALLOC_CTX *mem_ctx, + char **blob_description, + DATA_BLOB *blob) { VFS_FIND(sys_acl_blob_get_file); - return handle->fns->sys_acl_blob_get_file_fn(handle, path_p, mem_ctx, blob_description, blob); + return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname, + mem_ctx, blob_description, blob); } int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle, @@ -2297,11 +2491,13 @@ int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle, } int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle, - const char *name, SMB_ACL_TYPE_T acltype, - SMB_ACL_T theacl) + const struct smb_filename *smb_fname, + SMB_ACL_TYPE_T acltype, + SMB_ACL_T theacl) { VFS_FIND(sys_acl_set_file); - return handle->fns->sys_acl_set_file_fn(handle, name, acltype, theacl); + return handle->fns->sys_acl_set_file_fn(handle, smb_fname, + acltype, theacl); } int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle, @@ -2312,18 +2508,20 @@ int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle, } int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle, - const char *path) + const struct smb_filename *smb_fname) { VFS_FIND(sys_acl_delete_def_file); - return handle->fns->sys_acl_delete_def_file_fn(handle, path); + return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname); } ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle, - const char *path, const char *name, void *value, - size_t size) + const struct smb_filename *smb_fname, + const char *name, + void *value, + size_t size) { VFS_FIND(getxattr); - return handle->fns->getxattr_fn(handle, path, name, value, size); + return handle->fns->getxattr_fn(handle, smb_fname, name, value, size); } ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle, @@ -2335,10 +2533,12 @@ ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle, } ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle, - const char *path, char *list, size_t size) + const struct smb_filename *smb_fname, + char *list, + size_t size) { VFS_FIND(listxattr); - return handle->fns->listxattr_fn(handle, path, list, size); + return handle->fns->listxattr_fn(handle, smb_fname, list, size); } ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle, @@ -2350,10 +2550,11 @@ ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle, } int smb_vfs_call_removexattr(struct vfs_handle_struct *handle, - const char *path, const char *name) + const struct smb_filename *smb_fname, + const char *name) { VFS_FIND(removexattr); - return handle->fns->removexattr_fn(handle, path, name); + return handle->fns->removexattr_fn(handle, smb_fname, name); } int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle, @@ -2363,12 +2564,16 @@ int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle, return handle->fns->fremovexattr_fn(handle, fsp, name); } -int smb_vfs_call_setxattr(struct vfs_handle_struct *handle, const char *path, - const char *name, const void *value, size_t size, - int flags) +int smb_vfs_call_setxattr(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + const char *name, + const void *value, + size_t size, + int flags) { VFS_FIND(setxattr); - return handle->fns->setxattr_fn(handle, path, name, value, size, flags); + return handle->fns->setxattr_fn(handle, smb_fname, + name, value, size, flags); } int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle, @@ -2386,21 +2591,6 @@ bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle, return handle->fns->aio_force_fn(handle, fsp); } -bool smb_vfs_call_is_offline(struct vfs_handle_struct *handle, - const struct smb_filename *fname, - SMB_STRUCT_STAT *sbuf) -{ - VFS_FIND(is_offline); - return handle->fns->is_offline_fn(handle, fname, sbuf); -} - -int smb_vfs_call_set_offline(struct vfs_handle_struct *handle, - const struct smb_filename *fname) -{ - VFS_FIND(set_offline); - return handle->fns->set_offline_fn(handle, fname); -} - NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle, struct files_struct *fsp, TALLOC_CTX *mem_ctx, @@ -2434,3 +2624,12 @@ NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle, 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); +}