From: Samuel Cabrero Date: Wed, 8 Oct 2025 12:17:27 +0000 (+0200) Subject: smbd: Refactor reopen_from_fsp(), factor out pathref based X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=39d51636d81f707899b0bc1c76d1ad7ae4a9c9fe;p=thirdparty%2Fsamba.git smbd: Refactor reopen_from_fsp(), factor out pathref based Best viewed ignoring white space changes BUG: https://bugzilla.samba.org/show_bug.cgi?id=15805 Signed-off-by: Samuel Cabrero Reviewed-by: Ralph Boehme --- diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 081b85c80ec..4212f9ad32d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -896,68 +896,83 @@ static bool fsp_is_automount_mountpoint(struct files_struct *fsp, int old_fd) #endif } -NTSTATUS reopen_from_fsp(struct files_struct *dirfsp, - struct smb_filename *smb_fname, - struct files_struct *fsp, - const struct vfs_open_how *how, - bool *p_file_created) +static NTSTATUS reopen_from_fsp_pathref_based( + struct files_struct *dirfsp, + struct smb_filename *smb_fname, + struct files_struct *fsp, + const struct vfs_open_how *how, + bool *p_file_created) { NTSTATUS status; - int old_fd; + struct sys_proc_fd_path_buf buf; + int pathref_fd = fsp_get_pathref_fd(fsp); + struct smb_filename proc_fname = { + .base_name = sys_proc_fd_path(pathref_fd, &buf), + }; + mode_t mode = fsp->fsp_name->st.st_ex_mode; + int new_fd; - if (fsp->fsp_flags.have_proc_fds && - ((old_fd = fsp_get_pathref_fd(fsp)) != -1)) { + if (S_ISLNK(mode)) { + return NT_STATUS_STOPPED_ON_SYMLINK; + } + if (!(S_ISREG(mode) || S_ISDIR(mode))) { + return NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED; + } - struct sys_proc_fd_path_buf buf; - struct smb_filename proc_fname = { - .base_name = sys_proc_fd_path(old_fd, &buf), - }; - mode_t mode = fsp->fsp_name->st.st_ex_mode; - int new_fd; + fsp->fsp_flags.is_pathref = false; - if (S_ISLNK(mode)) { - return NT_STATUS_STOPPED_ON_SYMLINK; - } - if (!(S_ISREG(mode) || S_ISDIR(mode))) { - return NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED; + new_fd = SMB_VFS_OPENAT(fsp->conn, + fsp->conn->cwd_fsp, + &proc_fname, + fsp, + how); + if (new_fd == -1) { + int saved_errno = errno; + if (saved_errno == ENOENT && + fsp_is_automount_mountpoint(fsp, pathref_fd)) + { + /* + * When reopening an as-yet unmounted autofs + * mount point we get ENOENT. We have to retry + * pathbased. + */ + return reopen_from_fsp_namebased(dirfsp, + smb_fname, + fsp, + how, + p_file_created); } - fsp->fsp_flags.is_pathref = false; + status = map_nt_error_from_unix(saved_errno); + fd_close(fsp); + return status; + } - new_fd = SMB_VFS_OPENAT(fsp->conn, - fsp->conn->cwd_fsp, - &proc_fname, - fsp, - how); - if (new_fd == -1) { - int saved_errno = errno; - if (saved_errno == ENOENT && - fsp_is_automount_mountpoint(fsp, old_fd)) - { - /* - * When reopening an as-yet unmounted autofs - * mount point we get ENOENT. We have to retry - * pathbased. - */ - return reopen_from_fsp_namebased(dirfsp, - smb_fname, - fsp, - how, - p_file_created); - } + status = fd_close(fsp); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - status = map_nt_error_from_unix(saved_errno); - fd_close(fsp); - return status; - } + fsp_set_fd(fsp, new_fd); + return NT_STATUS_OK; +} - status = fd_close(fsp); - if (!NT_STATUS_IS_OK(status)) { - return status; - } +NTSTATUS reopen_from_fsp(struct files_struct *dirfsp, + struct smb_filename *smb_fname, + struct files_struct *fsp, + const struct vfs_open_how *how, + bool *p_file_created) +{ + int old_fd; - fsp_set_fd(fsp, new_fd); - return NT_STATUS_OK; + if (fsp->fsp_flags.have_proc_fds && + ((old_fd = fsp_get_pathref_fd(fsp)) != -1)) + { + return reopen_from_fsp_pathref_based(dirfsp, + smb_fname, + fsp, + how, + p_file_created); } return reopen_from_fsp_namebased(dirfsp,