From: Volker Lendecke Date: Tue, 16 Sep 2025 20:15:39 +0000 (-0700) Subject: smbd: Simplify hardlink_internals() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e02293b1a49d4efea9662f6e8cb667f8c14e9802;p=thirdparty%2Fsamba.git smbd: Simplify hardlink_internals() Avoid calling parent_pathref() in hardlink_internals. All but one callers have the required information anyway. Unfortunately the one that does not have it is the SMB2 one. So for SMB2+ this is not a real optimization, but in some distant future we might have a dirfsp attached to every fsp, so this might at some point also solve itself. Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme --- diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index dbc420d8027..b9e598810c3 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -1100,7 +1100,9 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, connection_struct *conn, struct smb_request *req, bool overwrite_if_exists, + struct files_struct *dirfsp_old, const struct smb_filename *smb_fname_old, + struct smb_filename *smb_fname_old_rel, struct files_struct *dirfsp_new, struct smb_filename *smb_fname_new, struct smb_filename *smb_fname_new_rel); diff --git a/source3/smbd/smb1_nttrans.c b/source3/smbd/smb1_nttrans.c index ed8cb67d14f..f6c8323a0dc 100644 --- a/source3/smbd/smb1_nttrans.c +++ b/source3/smbd/smb1_nttrans.c @@ -1420,6 +1420,7 @@ void reply_ntrename(struct smb_request *req) connection_struct *conn = req->conn; struct files_struct *src_dirfsp = NULL; struct smb_filename *smb_fname_old = NULL; + struct smb_filename *smb_fname_old_rel = NULL; struct files_struct *dst_dirfsp = NULL; struct smb_filename *smb_fname_new = NULL; struct smb_filename *smb_fname_new_rel = NULL; @@ -1480,13 +1481,15 @@ void reply_ntrename(struct smb_request *req) goto out; } - status = filename_convert_dirfsp(ctx, - conn, - oldname, - ucf_flags_src, - src_twrp, - &src_dirfsp, - &smb_fname_old); + status = filename_convert_dirfsp_rel(ctx, + conn, + conn->cwd_fsp, + oldname, + ucf_flags_src, + src_twrp, + &src_dirfsp, + &smb_fname_old, + &smb_fname_old_rel); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { @@ -1594,7 +1597,9 @@ void reply_ntrename(struct smb_request *req) conn, req, false, + src_dirfsp, smb_fname_old, + smb_fname_old_rel, dst_dirfsp, smb_fname_new, smb_fname_new_rel); diff --git a/source3/smbd/smb1_trans2.c b/source3/smbd/smb1_trans2.c index f76eeaf76b7..0fd72e6c724 100644 --- a/source3/smbd/smb1_trans2.c +++ b/source3/smbd/smb1_trans2.c @@ -3709,6 +3709,7 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, char *oldname = NULL; struct files_struct *src_dirfsp = NULL; struct smb_filename *smb_fname_old = NULL; + struct smb_filename *smb_fname_old_rel = NULL; uint32_t ucf_flags = ucf_flags_from_smb_request(req); NTTIME old_twrp = 0; TALLOC_CTX *ctx = talloc_tos(); @@ -3757,13 +3758,15 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { return status; } - status = filename_convert_dirfsp(ctx, - conn, - oldname, - ucf_flags, - old_twrp, - &src_dirfsp, - &smb_fname_old); + status = filename_convert_dirfsp_rel(ctx, + conn, + conn->cwd_fsp, + oldname, + ucf_flags, + old_twrp, + &src_dirfsp, + &smb_fname_old, + &smb_fname_old_rel); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -3772,7 +3775,9 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, conn, req, false, + src_dirfsp, smb_fname_old, + smb_fname_old_rel, dirfsp_new, smb_fname_new, smb_fname_new_rel); diff --git a/source3/smbd/smb2_trans2.c b/source3/smbd/smb2_trans2.c index 3577563850f..13b3689197f 100644 --- a/source3/smbd/smb2_trans2.c +++ b/source3/smbd/smb2_trans2.c @@ -3688,7 +3688,9 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, connection_struct *conn, struct smb_request *req, bool overwrite_if_exists, + struct files_struct *dirfsp_old, const struct smb_filename *smb_fname_old, + struct smb_filename *smb_fname_old_rel, struct files_struct *dirfsp_new, struct smb_filename *smb_fname_new, struct smb_filename *smb_fname_new_rel) @@ -3696,8 +3698,6 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, NTSTATUS status = NT_STATUS_OK; int ret; bool ok; - struct smb_filename *parent_fname_old = NULL; - struct smb_filename *base_name_old = NULL; /* source must already exist. */ if (!VALID_STAT(smb_fname_old->st)) { @@ -3730,15 +3730,6 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, goto out; } - status = parent_pathref(talloc_tos(), - conn->cwd_fsp, - smb_fname_old, - &parent_fname_old, - &base_name_old); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - if (VALID_STAT(smb_fname_new->st)) { if (overwrite_if_exists) { if (S_ISDIR(smb_fname_new->st.st_ex_mode)) { @@ -3765,8 +3756,8 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, smb_fname_new->base_name); ret = SMB_VFS_LINKAT(conn, - parent_fname_old->fsp, - base_name_old, + dirfsp_old, + smb_fname_old_rel, dirfsp_new, smb_fname_new_rel, 0); @@ -3788,8 +3779,6 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, fsp_get_smb2_lease(smb_fname_old->fsp)); out: - - TALLOC_FREE(parent_fname_old); return status; } @@ -4414,6 +4403,8 @@ static NTSTATUS smb_file_link_information(connection_struct *conn, bool overwrite; uint32_t len; char *newname = NULL; + struct smb_filename *src_parent = NULL; + struct smb_filename *smb_fname_src_rel = NULL; struct files_struct *dst_dirfsp = NULL; struct smb_filename *smb_fname_dst = NULL; struct smb_filename *smb_fname_dst_rel = NULL; @@ -4512,6 +4503,15 @@ static NTSTATUS smb_file_link_information(connection_struct *conn, return NT_STATUS_NOT_SUPPORTED; } + status = parent_pathref(ctx, + conn->cwd_fsp, + fsp->fsp_name, + &src_parent, + &smb_fname_src_rel); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n", fsp_fnum_dbg(fsp), fsp_str_dbg(fsp), @@ -4521,7 +4521,9 @@ static NTSTATUS smb_file_link_information(connection_struct *conn, conn, req, overwrite, + src_parent->fsp, fsp->fsp_name, + smb_fname_src_rel, dst_dirfsp, smb_fname_dst, smb_fname_dst_rel);