Skip to content

Commit

Permalink
Merge pull request #46410 from dalum/master
Browse files Browse the repository at this point in the history
Add mutating `stat!` function for non-allocating filesystem `stat`
  • Loading branch information
oscardssmith committed Jun 19, 2023
2 parents 82ab124 + 62e57f7 commit 427b123
Showing 1 changed file with 25 additions and 9 deletions.
34 changes: 25 additions & 9 deletions base/stat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -144,28 +144,44 @@ show(io::IO, ::MIME"text/plain", st::StatStruct) = show_statstruct(io, st, false

# stat & lstat functions

macro stat_call(sym, arg1type, arg)
macro stat_call!(stat_buf, sym, arg1type, arg)
return quote
stat_buf = zeros(UInt8, Int(ccall(:jl_sizeof_stat, Int32, ())))
r = ccall($(Expr(:quote, sym)), Int32, ($(esc(arg1type)), Ptr{UInt8}), $(esc(arg)), stat_buf)
r = ccall($(Expr(:quote, sym)), Int32, ($(esc(arg1type)), Ptr{UInt8}), $(esc(arg)), $(esc(stat_buf)))
if !(r in (0, Base.UV_ENOENT, Base.UV_ENOTDIR, Base.UV_EINVAL))
uv_error(string("stat(", repr($(esc(arg))), ")"), r)
end
st = StatStruct($(esc(arg)), stat_buf)
st = StatStruct($(esc(arg)), $(esc(stat_buf)))
if ispath(st) != (r == 0)
error("stat returned zero type for a valid path")
end
return st
end
end

stat(fd::OS_HANDLE) = @stat_call jl_fstat OS_HANDLE fd
stat(path::AbstractString) = @stat_call jl_stat Cstring path
lstat(path::AbstractString) = @stat_call jl_lstat Cstring path
"""
stat!(stat_buf::Vector{UInt8}, file)
Like [`stat`](@ref), but avoids internal allocations by using a pre-allocated buffer,
`stat_buf`. For a small performance gain over `stat`, consecutive calls to `stat!` can use
the same `stat_buf`. See also [`Base.Filesystem.get_stat_buf`](@ref).
"""
stat!(stat_buf::Vector{UInt8}, fd::OS_HANDLE) = @stat_call! stat_buf jl_fstat OS_HANDLE fd
stat!(stat_buf::Vector{UInt8}, path::AbstractString) = @stat_call! stat_buf jl_stat Cstring path
lstat!(stat_buf::Vector{UInt8}, path::AbstractString) = @stat_call! stat_buf jl_lstat Cstring path
if RawFD !== OS_HANDLE
global stat(fd::RawFD) = stat(Libc._get_osfhandle(fd))
global stat!(stat_buf::Vector{UInt8}, fd::RawFD) = stat!(stat_buf, Libc._get_osfhandle(fd))
end
stat(fd::Integer) = stat(RawFD(fd))
stat!(stat_buf::Vector{UInt8}, fd::Integer) = stat!(stat_buf, RawFD(fd))

stat(x) = stat!(get_stat_buf(), x)
lstat(x) = lstat!(get_stat_buf(), x)

"""
get_stat_buf()
Return a buffer of bytes of the right size for [`stat!`](@ref).
"""
get_stat_buf() = zeros(UInt8, Int(ccall(:jl_sizeof_stat, Int32, ())))

"""
stat(file)
Expand Down

0 comments on commit 427b123

Please sign in to comment.