#include <sys/synch.h>
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_fsops.h>
#include <sys/nbmlock.h>
#define SMB_NT_RENAME_MOVE_CLUSTER_INFO 0x0102
#define SMB_NT_RENAME_SET_LINK_INFO 0x0103
#define SMB_NT_RENAME_RENAME_FILE 0x0104
#define SMB_NT_RENAME_MOVE_FILE 0x0105
smb_sdrc_t
smb_pre_rename(smb_request_t *sr)
{
smb_fqi_t *src_fqi = &sr->arg.dirop.fqi;
smb_fqi_t *dst_fqi = &sr->arg.dirop.dst_fqi;
int rc;
if ((rc = smbsr_decode_vwv(sr, "w", &src_fqi->fq_sattr)) == 0) {
rc = smbsr_decode_data(sr, "%SS", sr, &src_fqi->fq_path.pn_path,
&dst_fqi->fq_path.pn_path);
dst_fqi->fq_sattr = 0;
}
DTRACE_SMB_START(op__Rename, smb_request_t *, sr);
return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
void
smb_post_rename(smb_request_t *sr)
{
DTRACE_SMB_DONE(op__Rename, smb_request_t *, sr);
}
smb_sdrc_t
smb_com_rename(smb_request_t *sr)
{
smb_fqi_t *src_fqi = &sr->arg.dirop.fqi;
smb_fqi_t *dst_fqi = &sr->arg.dirop.dst_fqi;
smb_pathname_t *src_pn = &src_fqi->fq_path;
smb_pathname_t *dst_pn = &dst_fqi->fq_path;
uint32_t status;
if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
ERRDOS, ERROR_ACCESS_DENIED);
return (SDRC_ERROR);
}
smb_pathname_init(sr, src_pn, src_pn->pn_path);
smb_pathname_init(sr, dst_pn, dst_pn->pn_path);
if (!smb_pathname_validate(sr, src_pn) ||
!smb_pathname_validate(sr, dst_pn)) {
return (SDRC_ERROR);
}
status = smb_common_rename(sr, src_fqi, dst_fqi);
if (status != 0) {
smbsr_error(sr, status, 0, 0);
return (SDRC_ERROR);
}
(void) smbsr_encode_empty_result(sr);
return (SDRC_SUCCESS);
}
smb_sdrc_t
smb_pre_nt_rename(smb_request_t *sr)
{
smb_fqi_t *src_fqi = &sr->arg.dirop.fqi;
smb_fqi_t *dst_fqi = &sr->arg.dirop.dst_fqi;
uint32_t clusters;
int rc;
rc = smbsr_decode_vwv(sr, "wwl", &src_fqi->fq_sattr,
&sr->arg.dirop.info_level, &clusters);
if (rc == 0) {
rc = smbsr_decode_data(sr, "%SS", sr,
&src_fqi->fq_path.pn_path, &dst_fqi->fq_path.pn_path);
dst_fqi->fq_sattr = 0;
}
DTRACE_SMB_START(op__NtRename, smb_request_t *, sr);
return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
void
smb_post_nt_rename(smb_request_t *sr)
{
DTRACE_SMB_DONE(op__NtRename, smb_request_t *, sr);
}
smb_sdrc_t
smb_com_nt_rename(smb_request_t *sr)
{
smb_fqi_t *src_fqi = &sr->arg.dirop.fqi;
smb_fqi_t *dst_fqi = &sr->arg.dirop.dst_fqi;
smb_pathname_t *src_pn = &src_fqi->fq_path;
smb_pathname_t *dst_pn = &dst_fqi->fq_path;
uint32_t status;
if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
ERRDOS, ERROR_ACCESS_DENIED);
return (SDRC_ERROR);
}
smb_pathname_init(sr, src_pn, src_pn->pn_path);
smb_pathname_init(sr, dst_pn, dst_pn->pn_path);
if (!smb_pathname_validate(sr, src_pn) ||
!smb_pathname_validate(sr, dst_pn)) {
return (SDRC_ERROR);
}
if (smb_contains_wildcards(src_pn->pn_path)) {
smbsr_error(sr, NT_STATUS_OBJECT_PATH_SYNTAX_BAD,
ERRDOS, ERROR_BAD_PATHNAME);
return (SDRC_ERROR);
}
switch (sr->arg.dirop.info_level) {
case SMB_NT_RENAME_SET_LINK_INFO:
status = smb_make_link(sr, src_fqi, dst_fqi);
break;
case SMB_NT_RENAME_RENAME_FILE:
case SMB_NT_RENAME_MOVE_FILE:
status = smb_common_rename(sr, src_fqi, dst_fqi);
break;
case SMB_NT_RENAME_MOVE_CLUSTER_INFO:
status = NT_STATUS_INVALID_PARAMETER;
break;
default:
status = NT_STATUS_ACCESS_DENIED;
break;
}
if (status != 0) {
smbsr_error(sr, status, 0, 0);
return (SDRC_ERROR);
}
(void) smbsr_encode_empty_result(sr);
return (SDRC_SUCCESS);
}
smb_sdrc_t
smb_nt_transact_rename(smb_request_t *sr, smb_xa_t *xa)
{
if (smb_mbc_decodef(&xa->req_param_mb, "w", &sr->smb_fid) != 0)
return (SDRC_ERROR);
smbsr_lookup_file(sr);
if (sr->fid_ofile == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
return (SDRC_ERROR);
}
smbsr_release_file(sr);
return (SDRC_SUCCESS);
}