Skip to content

Commit 0305b7c

Browse files
authored
Backport prepare_for_deletion() (#38159)
1 parent 37c1096 commit 0305b7c

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

base/file.jl

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,32 @@ function tempdir()
458458
end
459459
end
460460

461+
"""
462+
prepare_for_deletion(path::AbstractString)
463+
464+
Prepares the given `path` for deletion by ensuring that all directories within that
465+
`path` have write permissions, so that files can be removed from them. This is
466+
automatically invoked by methods such as `mktempdir()` to ensure that no matter what
467+
weird permissions a user may have created directories with within the temporary prefix,
468+
it will always be deleted.
469+
"""
470+
function prepare_for_deletion(path::AbstractString)
471+
# Nothing to do for non-directories
472+
if !isdir(path)
473+
return
474+
end
475+
476+
try chmod(path, filemode(path) | 0o333)
477+
catch; end
478+
for (root, dirs, files) in walkdir(path)
479+
for dir in dirs
480+
dpath = joinpath(root, dir)
481+
try chmod(dpath, filemode(dpath) | 0o333)
482+
catch; end
483+
end
484+
end
485+
end
486+
461487
const TEMP_CLEANUP_MIN = Ref(1024)
462488
const TEMP_CLEANUP_MAX = Ref(1024)
463489
const TEMP_CLEANUP = Dict{String,Bool}()
@@ -484,6 +510,7 @@ function temp_cleanup_purge(all::Bool=true)
484510
if (all || asap) && ispath(path)
485511
need_gc && GC.gc(true)
486512
need_gc = false
513+
prepare_for_deletion(path)
487514
rm(path, recursive=true, force=true)
488515
end
489516
!ispath(path) && delete!(TEMP_CLEANUP, path)
@@ -682,7 +709,10 @@ function mktempdir(fn::Function, parent::AbstractString=tempdir();
682709
fn(tmpdir)
683710
finally
684711
try
685-
ispath(tmpdir) && rm(tmpdir, recursive=true)
712+
if ispath(tmpdir)
713+
prepare_for_deletion(tmpdir)
714+
rm(tmpdir, recursive=true)
715+
end
686716
catch ex
687717
@error "mktempdir cleanup" _group=:file exception=(ex, catch_backtrace())
688718
# might be possible to remove later

test/file.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,20 @@ no_error_logging(f::Function) =
268268
end
269269
end
270270

271+
@testset "mktempdir() permissions correction" begin
272+
# Test that `mktempdir()` with children with weird permissions get cleared
273+
# before we would delete the directory
274+
local temp_dir_path
275+
mktempdir() do dir
276+
temp_dir_path = dir
277+
mkdir(joinpath(dir, "foo"))
278+
touch(joinpath(dir, "foo", "bar"))
279+
chmod(joinpath(dir, "foo"), 0o444)
280+
@test isdir(temp_dir_path)
281+
end
282+
@test !isdir(temp_dir_path)
283+
end
284+
271285
#######################################################################
272286
# This section tests some of the features of the stat-based file info #
273287
#######################################################################

0 commit comments

Comments
 (0)