1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-09 08:58:35 +03:00

smbd: Move copy_internals to smb2_nttrans.c

Signed-off-by: David Mulder <dmulder@suse.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
David Mulder 2022-03-11 12:06:38 -07:00 committed by Jeremy Allison
parent 7e88a86a15
commit 17e04761cb
3 changed files with 183 additions and 183 deletions

View File

@ -1386,183 +1386,6 @@ void reply_ntcancel(struct smb_request *req)
return;
}
/****************************************************************************
Copy a file.
****************************************************************************/
NTSTATUS copy_internals(TALLOC_CTX *ctx,
connection_struct *conn,
struct smb_request *req,
struct smb_filename *smb_fname_src,
struct smb_filename *smb_fname_dst,
uint32_t attrs)
{
files_struct *fsp1,*fsp2;
uint32_t fattr;
int info;
off_t ret=-1;
NTSTATUS status = NT_STATUS_OK;
struct smb_filename *parent = NULL;
struct smb_filename *pathref = NULL;
if (!CAN_WRITE(conn)) {
status = NT_STATUS_MEDIA_WRITE_PROTECTED;
goto out;
}
/* Source must already exist. */
if (!VALID_STAT(smb_fname_src->st)) {
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
goto out;
}
/* Ensure attributes match. */
fattr = fdos_mode(smb_fname_src->fsp);
if ((fattr & ~attrs) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
status = NT_STATUS_NO_SUCH_FILE;
goto out;
}
/* Disallow if dst file already exists. */
if (VALID_STAT(smb_fname_dst->st)) {
status = NT_STATUS_OBJECT_NAME_COLLISION;
goto out;
}
/* No links from a directory. */
if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
status = NT_STATUS_FILE_IS_A_DIRECTORY;
goto out;
}
DEBUG(10,("copy_internals: doing file copy %s to %s\n",
smb_fname_str_dbg(smb_fname_src),
smb_fname_str_dbg(smb_fname_dst)));
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
smb_fname_src, /* fname */
FILE_READ_DATA|FILE_READ_ATTRIBUTES|
FILE_READ_EA, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
FILE_OPEN, /* create_disposition*/
0, /* create_options */
FILE_ATTRIBUTE_NORMAL, /* file_attributes */
NO_OPLOCK, /* oplock_request */
NULL, /* lease */
0, /* allocation_size */
0, /* private_flags */
NULL, /* sd */
NULL, /* ea_list */
&fsp1, /* result */
&info, /* pinfo */
NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
smb_fname_dst, /* fname */
FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|
FILE_WRITE_EA, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
FILE_CREATE, /* create_disposition*/
0, /* create_options */
fattr, /* file_attributes */
NO_OPLOCK, /* oplock_request */
NULL, /* lease */
0, /* allocation_size */
0, /* private_flags */
NULL, /* sd */
NULL, /* ea_list */
&fsp2, /* result */
&info, /* pinfo */
NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(status)) {
close_file_free(NULL, &fsp1, ERROR_CLOSE);
goto out;
}
if (smb_fname_src->st.st_ex_size) {
ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
}
/*
* As we are opening fsp1 read-only we only expect
* an error on close on fsp2 if we are out of space.
* Thus we don't look at the error return from the
* close of fsp1.
*/
close_file_free(NULL, &fsp1, NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
status = close_file_free(NULL, &fsp2, NORMAL_CLOSE);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("close_file_free() failed: %s\n",
nt_errstr(status));
/*
* We can't do much but leak the fsp
*/
goto out;
}
/* Grrr. We have to do this as open_file_ntcreate adds FILE_ATTRIBUTE_ARCHIVE when it
creates the file. This isn't the correct thing to do in the copy
case. JRA */
status = SMB_VFS_PARENT_PATHNAME(conn,
talloc_tos(),
smb_fname_dst,
&parent,
NULL);
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
if (smb_fname_dst->fsp == NULL) {
status = synthetic_pathref(parent,
conn->cwd_fsp,
smb_fname_dst->base_name,
smb_fname_dst->stream_name,
NULL,
smb_fname_dst->twrp,
smb_fname_dst->flags,
&pathref);
/* should we handle NT_STATUS_OBJECT_NAME_NOT_FOUND specially here ???? */
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(parent);
goto out;
}
file_set_dosmode(conn, pathref, fattr, parent, false);
smb_fname_dst->st.st_ex_mode = pathref->st.st_ex_mode;
} else {
file_set_dosmode(conn, smb_fname_dst, fattr, parent, false);
}
TALLOC_FREE(parent);
if (ret < (off_t)smb_fname_src->st.st_ex_size) {
status = NT_STATUS_DISK_FULL;
goto out;
}
out:
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
smb_fname_str_dbg(smb_fname_dst)));
}
return status;
}
/****************************************************************************
Reply to a NT rename request.
****************************************************************************/

View File

@ -685,12 +685,6 @@ NTSTATUS smbd_do_query_security_desc(connection_struct *conn,
uint32_t max_data_count,
uint8_t **ppmarshalled_sd,
size_t *psd_size);
NTSTATUS copy_internals(TALLOC_CTX *ctx,
connection_struct *conn,
struct smb_request *req,
struct smb_filename *smb_fname_src,
struct smb_filename *smb_fname_dst,
uint32_t attrs);
#ifdef HAVE_SYS_QUOTAS
struct smb2_query_quota_info;
@ -714,6 +708,12 @@ NTSTATUS set_sd(files_struct *fsp, struct security_descriptor *psd,
uint32_t security_info_sent);
NTSTATUS set_sd_blob(files_struct *fsp, uint8_t *data, uint32_t sd_len,
uint32_t security_info_sent);
NTSTATUS copy_internals(TALLOC_CTX *ctx,
connection_struct *conn,
struct smb_request *req,
struct smb_filename *smb_fname_src,
struct smb_filename *smb_fname_dst,
uint32_t attrs);
/* The following definitions come from smbd/open.c */

View File

@ -189,3 +189,180 @@ NTSTATUS set_sd_blob(files_struct *fsp, uint8_t *data, uint32_t sd_len,
return set_sd(fsp, psd, security_info_sent);
}
/****************************************************************************
Copy a file.
****************************************************************************/
NTSTATUS copy_internals(TALLOC_CTX *ctx,
connection_struct *conn,
struct smb_request *req,
struct smb_filename *smb_fname_src,
struct smb_filename *smb_fname_dst,
uint32_t attrs)
{
files_struct *fsp1,*fsp2;
uint32_t fattr;
int info;
off_t ret=-1;
NTSTATUS status = NT_STATUS_OK;
struct smb_filename *parent = NULL;
struct smb_filename *pathref = NULL;
if (!CAN_WRITE(conn)) {
status = NT_STATUS_MEDIA_WRITE_PROTECTED;
goto out;
}
/* Source must already exist. */
if (!VALID_STAT(smb_fname_src->st)) {
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
goto out;
}
/* Ensure attributes match. */
fattr = fdos_mode(smb_fname_src->fsp);
if ((fattr & ~attrs) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
status = NT_STATUS_NO_SUCH_FILE;
goto out;
}
/* Disallow if dst file already exists. */
if (VALID_STAT(smb_fname_dst->st)) {
status = NT_STATUS_OBJECT_NAME_COLLISION;
goto out;
}
/* No links from a directory. */
if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
status = NT_STATUS_FILE_IS_A_DIRECTORY;
goto out;
}
DEBUG(10,("copy_internals: doing file copy %s to %s\n",
smb_fname_str_dbg(smb_fname_src),
smb_fname_str_dbg(smb_fname_dst)));
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
smb_fname_src, /* fname */
FILE_READ_DATA|FILE_READ_ATTRIBUTES|
FILE_READ_EA, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
FILE_OPEN, /* create_disposition*/
0, /* create_options */
FILE_ATTRIBUTE_NORMAL, /* file_attributes */
NO_OPLOCK, /* oplock_request */
NULL, /* lease */
0, /* allocation_size */
0, /* private_flags */
NULL, /* sd */
NULL, /* ea_list */
&fsp1, /* result */
&info, /* pinfo */
NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
smb_fname_dst, /* fname */
FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|
FILE_WRITE_EA, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
FILE_CREATE, /* create_disposition*/
0, /* create_options */
fattr, /* file_attributes */
NO_OPLOCK, /* oplock_request */
NULL, /* lease */
0, /* allocation_size */
0, /* private_flags */
NULL, /* sd */
NULL, /* ea_list */
&fsp2, /* result */
&info, /* pinfo */
NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(status)) {
close_file_free(NULL, &fsp1, ERROR_CLOSE);
goto out;
}
if (smb_fname_src->st.st_ex_size) {
ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
}
/*
* As we are opening fsp1 read-only we only expect
* an error on close on fsp2 if we are out of space.
* Thus we don't look at the error return from the
* close of fsp1.
*/
close_file_free(NULL, &fsp1, NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
status = close_file_free(NULL, &fsp2, NORMAL_CLOSE);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("close_file_free() failed: %s\n",
nt_errstr(status));
/*
* We can't do much but leak the fsp
*/
goto out;
}
/* Grrr. We have to do this as open_file_ntcreate adds FILE_ATTRIBUTE_ARCHIVE when it
creates the file. This isn't the correct thing to do in the copy
case. JRA */
status = SMB_VFS_PARENT_PATHNAME(conn,
talloc_tos(),
smb_fname_dst,
&parent,
NULL);
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
if (smb_fname_dst->fsp == NULL) {
status = synthetic_pathref(parent,
conn->cwd_fsp,
smb_fname_dst->base_name,
smb_fname_dst->stream_name,
NULL,
smb_fname_dst->twrp,
smb_fname_dst->flags,
&pathref);
/* should we handle NT_STATUS_OBJECT_NAME_NOT_FOUND specially here ???? */
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(parent);
goto out;
}
file_set_dosmode(conn, pathref, fattr, parent, false);
smb_fname_dst->st.st_ex_mode = pathref->st.st_ex_mode;
} else {
file_set_dosmode(conn, smb_fname_dst, fattr, parent, false);
}
TALLOC_FREE(parent);
if (ret < (off_t)smb_fname_src->st.st_ex_size) {
status = NT_STATUS_DISK_FULL;
goto out;
}
out:
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
smb_fname_str_dbg(smb_fname_dst)));
}
return status;
}