diff --git a/base/stat.jl b/base/stat.jl index 81f9dcfd20191..84c5c33a5fdf7 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -144,14 +144,13 @@ 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 @@ -159,13 +158,30 @@ macro stat_call(sym, arg1type, arg) 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)