* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "includes.h"
+#include "system/filesys.h"
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <dirent.h>
#include <libgen.h>
-#include "system/filesys.h"
-#include "includes.h"
#include "smbd/smbd.h"
#include "smbd/globals.h"
#include "librpc/gen_ndr/smbXsrv.h"
struct btrfs_offload_read_state {
struct vfs_handle_struct *handle;
files_struct *fsp;
+ uint32_t flags;
+ uint64_t xferlen;
DATA_BLOB token;
};
status = SMB_VFS_NEXT_OFFLOAD_READ_RECV(subreq,
state->handle,
state,
+ &state->flags,
+ &state->xferlen,
&state->token);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
static NTSTATUS btrfs_offload_read_recv(struct tevent_req *req,
struct vfs_handle_struct *handle,
TALLOC_CTX *mem_ctx,
+ uint32_t *flags,
+ uint64_t *xferlen,
DATA_BLOB *token)
{
struct btrfs_offload_read_state *state = tevent_req_data(
return status;
}
+ *flags = state->flags;
+ *xferlen = state->xferlen;
token->length = state->token.length;
token->data = talloc_move(mem_ctx, &state->token.data);
struct btrfs_offload_write_state {
struct vfs_handle_struct *handle;
off_t copied;
+ bool need_unbecome_user;
};
+
+static void btrfs_offload_write_cleanup(struct tevent_req *req,
+ enum tevent_req_state req_state)
+{
+ struct btrfs_offload_write_state *state =
+ tevent_req_data(req,
+ struct btrfs_offload_write_state);
+ bool ok;
+
+ if (!state->need_unbecome_user) {
+ return;
+ }
+
+ ok = unbecome_user_without_service();
+ SMB_ASSERT(ok);
+ state->need_unbecome_user = false;
+}
+
static void btrfs_offload_write_done(struct tevent_req *subreq);
static struct tevent_req *btrfs_offload_write_send(struct vfs_handle_struct *handle,
bool handle_offload_write = true;
bool do_locking = false;
NTSTATUS status;
+ bool ok;
req = tevent_req_create(mem_ctx, &state,
struct btrfs_offload_write_state);
state->handle = handle;
+ tevent_req_set_cleanup_fn(req, btrfs_offload_write_cleanup);
+
status = vfs_offload_token_db_fetch_fsp(btrfs_offload_ctx,
token, &src_fsp);
if (tevent_req_nterror(req, status)) {
return tevent_req_post(req, ev);
}
+ ok = become_user_without_service_by_fsp(src_fsp);
+ if (!ok) {
+ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return tevent_req_post(req, ev);
+ }
+ state->need_unbecome_user = true;
+
status = vfs_stat_fsp(src_fsp);
if (tevent_req_nterror(req, status)) {
return tevent_req_post(req, ev);
src_off,
num,
READ_LOCK,
+ lp_posix_cifsu_locktype(src_fsp),
&src_lck);
+ if (!SMB_VFS_STRICT_LOCK_CHECK(src_fsp->conn, src_fsp, &src_lck)) {
+ tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+ return tevent_req_post(req, ev);
+ }
+ }
+
+ ok = unbecome_user_without_service();
+ SMB_ASSERT(ok);
+ state->need_unbecome_user = false;
+
+ if (do_locking) {
init_strict_lock_struct(dest_fsp,
- dest_fsp->op->global->open_persistent_id,
+ dest_fsp->op->global->open_persistent_id,
dest_off,
num,
WRITE_LOCK,
+ lp_posix_cifsu_locktype(dest_fsp),
&dest_lck);
- if (!SMB_VFS_STRICT_LOCK_CHECK(src_fsp->conn, src_fsp, &src_lck)) {
- tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
- return tevent_req_post(req, ev);
- }
if (!SMB_VFS_STRICT_LOCK_CHECK(dest_fsp->conn, dest_fsp, &dest_lck)) {
tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
return tevent_req_post(req, ev);
}
ZERO_STRUCT(cr_args);
- cr_args.src_fd = src_fsp->fh->fd;
+ cr_args.src_fd = fsp_get_io_fd(src_fsp);
cr_args.src_offset = (uint64_t)src_off;
cr_args.dest_offset = (uint64_t)dest_off;
cr_args.src_length = (uint64_t)num;
- ret = ioctl(dest_fsp->fh->fd, BTRFS_IOC_CLONE_RANGE, &cr_args);
+ ret = ioctl(fsp_get_io_fd(dest_fsp), BTRFS_IOC_CLONE_RANGE, &cr_args);
if (ret < 0) {
/*
* BTRFS_IOC_CLONE_RANGE only supports 'sectorsize' aligned
(unsigned long long)cr_args.src_length,
(long long)cr_args.src_fd,
(unsigned long long)cr_args.src_offset,
- dest_fsp->fh->fd,
+ fsp_get_io_fd(dest_fsp),
(unsigned long long)cr_args.dest_offset));
subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle,
state,
return NT_STATUS_OK;
}
-/*
- * caller must pass a non-null fsp or smb_fname. If fsp is null, then
- * fall back to opening the corresponding file to issue the ioctl.
- */
-static NTSTATUS btrfs_get_compression(struct vfs_handle_struct *handle,
- TALLOC_CTX *mem_ctx,
- struct files_struct *fsp,
- struct smb_filename *smb_fname,
- uint16_t *_compression_fmt)
+static NTSTATUS btrfs_fget_compression(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ struct files_struct *fsp,
+ uint16_t *_compression_fmt)
{
+ struct sys_proc_fd_path_buf buf;
int ret;
long flags = 0;
- int fd;
- bool opened = false;
+ int fsp_fd = fsp_get_pathref_fd(fsp);
+ int fd = -1;
NTSTATUS status;
- DIR *dir = NULL;
-
- if ((fsp != NULL) && (fsp->fh->fd != -1)) {
- fd = fsp->fh->fd;
- } else if (smb_fname != NULL) {
- if (S_ISDIR(smb_fname->st.st_ex_mode)) {
- dir = opendir(smb_fname->base_name);
- if (dir == NULL) {
- return NT_STATUS_UNSUCCESSFUL;
- }
- opened = true;
- fd = dirfd(dir);
- if (fd < 0) {
- status = NT_STATUS_UNSUCCESSFUL;
- goto err_close;
- }
+
+ if (!fsp->fsp_flags.is_pathref) {
+ ret = ioctl(fsp_fd, FS_IOC_GETFLAGS, &flags);
+ if (ret < 0) {
+ DBG_WARNING("FS_IOC_GETFLAGS failed: %s, fd %lld\n",
+ strerror(errno), (long long)fd);
+ return map_nt_error_from_unix(errno);
+ }
+ if (flags & FS_COMPR_FL) {
+ *_compression_fmt = COMPRESSION_FORMAT_LZNT1;
} else {
- fd = open(smb_fname->base_name, O_RDONLY);
- if (fd < 0) {
- return NT_STATUS_UNSUCCESSFUL;
- }
- opened = true;
+ *_compression_fmt = COMPRESSION_FORMAT_NONE;
}
- } else {
- return NT_STATUS_INVALID_PARAMETER;
+ return NT_STATUS_OK;
+ }
+
+ if (!fsp->fsp_flags.have_proc_fds) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ fd = open(sys_proc_fd_path(fsp_fd, &buf), O_RDONLY);
+ if (fd == -1) {
+ DBG_DEBUG("/proc open of %s failed: %s\n",
+ buf.buf,
+ strerror(errno));
+ return map_nt_error_from_unix(errno);
}
ret = ioctl(fd, FS_IOC_GETFLAGS, &flags);
*_compression_fmt = COMPRESSION_FORMAT_NONE;
}
status = NT_STATUS_OK;
+
err_close:
- if (opened) {
- if (dir != NULL) {
- closedir(dir);
- } else {
- close(fd);
- }
+ if (fd != -1) {
+ close(fd);
}
return status;
int fd;
NTSTATUS status;
- if ((fsp == NULL) || (fsp->fh->fd == -1)) {
+ if ((fsp == NULL) || (fsp_get_io_fd(fsp) == -1)) {
status = NT_STATUS_INVALID_PARAMETER;
goto err_out;
}
- fd = fsp->fh->fd;
+ fd = fsp_get_io_fd(fsp);
ret = ioctl(fd, FS_IOC_GETFLAGS, &flags);
if (ret < 0) {
char *snap_path)
{
char *tstr;
- struct tm t_gmt;
+ struct tm t_gmt = {};
DIR *dest_dir;
int dest_fd;
struct btrfs_ioctl_vol_args ioctl_arg;
.offload_read_recv_fn = btrfs_offload_read_recv,
.offload_write_send_fn = btrfs_offload_write_send,
.offload_write_recv_fn = btrfs_offload_write_recv,
- .get_compression_fn = btrfs_get_compression,
+ .fget_compression_fn = btrfs_fget_compression,
.set_compression_fn = btrfs_set_compression,
.snap_check_path_fn = btrfs_snap_check_path,
.snap_create_fn = btrfs_snap_create,