1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-21 18:04:06 +03:00

smbd: Streamline recursive_rmdir()

By factoring out recursive_rmdir_fsp() we can do the recursion using
openat_pathref_fsp_lcomp(). This makes strace for a recursive
directory removal look a *lot* cleaner.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Pavel Filipenský <pfilipensky@samba.org>
This commit is contained in:
Volker Lendecke 2024-12-06 09:19:08 +01:00
parent 663f03996c
commit 83f7129e58

View File

@ -974,10 +974,9 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
return status;
}
NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
connection_struct *conn,
struct smb_filename *smb_dname)
static NTSTATUS recursive_rmdir_fsp(struct files_struct *fsp)
{
struct connection_struct *conn = fsp->conn;
const char *dname = NULL;
char *talloced = NULL;
struct smb_Dir *dir_hnd = NULL;
@ -985,14 +984,7 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
int retval;
NTSTATUS status = NT_STATUS_OK;
SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
status = OpenDir(talloc_tos(),
conn,
smb_dname,
NULL,
0,
&dir_hnd);
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@ -1001,9 +993,6 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
while ((dname = ReadDirName(dir_hnd, &talloced))) {
struct smb_filename *atname = NULL;
struct smb_filename *smb_dname_full = NULL;
char *fullname = NULL;
bool do_break = true;
int unlink_flags = 0;
if (ISDOT(dname) || ISDOTDOT(dname)) {
@ -1011,56 +1000,56 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
continue;
}
/* Construct the full name. */
fullname = talloc_asprintf(ctx,
"%s/%s",
smb_dname->base_name,
dname);
if (!fullname) {
atname = synthetic_smb_fname(talloc_tos(),
dname,
NULL,
NULL,
dirfsp->fsp_name->twrp,
dirfsp->fsp_name->flags);
TALLOC_FREE(talloced);
dname = NULL;
if (atname == NULL) {
status = NT_STATUS_NO_MEMORY;
goto err_break;
break;
}
smb_dname_full = synthetic_smb_fname(talloc_tos(),
fullname,
NULL,
NULL,
smb_dname->twrp,
smb_dname->flags);
if (smb_dname_full == NULL) {
status = NT_STATUS_NO_MEMORY;
goto err_break;
{
struct name_compare_entry *veto_list = conn->veto_list;
/*
* Sneaky hack to be able to open veto files
* with openat_pathref_fsp
*/
conn->veto_list = NULL;
status = openat_pathref_fsp_lcomp(
dirfsp,
atname,
UCF_POSIX_PATHNAMES /* no ci fallback */);
conn->veto_list = veto_list;
}
if (SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
status = map_nt_error_from_unix(errno);
goto err_break;
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(atname);
if (NT_STATUS_EQUAL(status,
NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
/* race between readdir and unlink */
continue;
}
break;
}
if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
status = recursive_rmdir(ctx, conn, smb_dname_full);
if (atname->st.st_ex_mode & S_IFDIR) {
status = recursive_rmdir_fsp(atname->fsp);
if (!NT_STATUS_IS_OK(status)) {
goto err_break;
TALLOC_FREE(atname);
break;
}
unlink_flags = AT_REMOVEDIR;
}
status = synthetic_pathref(talloc_tos(),
dirfsp,
dname,
NULL,
&smb_dname_full->st,
smb_dname_full->twrp,
smb_dname_full->flags,
&atname);
if (!NT_STATUS_IS_OK(status)) {
goto err_break;
}
if (!is_visible_fsp(atname->fsp)) {
TALLOC_FREE(smb_dname_full);
TALLOC_FREE(fullname);
TALLOC_FREE(talloced);
TALLOC_FREE(atname);
continue;
}
@ -1071,25 +1060,34 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
unlink_flags);
if (retval != 0) {
status = map_nt_error_from_unix(errno);
goto err_break;
}
/* Successful iteration. */
do_break = false;
err_break:
TALLOC_FREE(smb_dname_full);
TALLOC_FREE(fullname);
TALLOC_FREE(talloced);
TALLOC_FREE(atname);
if (do_break) {
TALLOC_FREE(atname);
break;
}
}
TALLOC_FREE(atname);
}
TALLOC_FREE(dir_hnd);
return status;
}
NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
connection_struct *conn,
struct smb_filename *smb_dname)
{
NTSTATUS status;
SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
status = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
status = recursive_rmdir_fsp(smb_dname->fsp);
return status;
}
/****************************************************************************
The internals of the rmdir code - called elsewhere.
****************************************************************************/