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:
parent
7e88a86a15
commit
17e04761cb
@ -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.
|
||||
****************************************************************************/
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user