From 010c589d5d057463956ffd3b9a9656c2b78b32ef Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 26 Sep 2022 15:41:46 +1300 Subject: [PATCH 01/10] WIP: Implement primitive system ishidden check from Obj-C functions Getting back to the task of checking whether a directory is a _system_ directory, I reviewed an old link I posted in #1: https://stackoverflow.com/a/1140345/12069968. While a lot of these function appear to be deprecated now, it seems to work somewhat well. For example, `_isinvisible_alt` returns `true` on all UNIX-specific directories listed in the macOS resources for this type of hidden file. We still need to: - Implement tests for all of these UNIX-specific directories; - Find non-deprecated system calls to obtain the same information; - Correctly construct LSItemInfoRecord (rather than allocating a reasonably large buffer because I don't know how large it needs to be), and find the correct offset for flags. Addresses #1 Ref: https://github.com/jakewilliami/HiddenFiles.jl/issues/1#issuecomment-1225585227 ``` julia> HiddenFiles._isinvisible_alt("/bin") true julia> HiddenFiles._isinvisible_alt("/dev/") true julia> HiddenFiles._isinvisible_alt("/dev") true julia> HiddenFiles._isinvisible_alt("/etc") true julia> HiddenFiles._isinvisible_alt("/sbin/") true julia> HiddenFiles._isinvisible_alt("/sbin") true julia> HiddenFiles._isinvisible_alt("/tmp") true julia> HiddenFiles._isinvisible_alt("/usr") true julia> HiddenFiles._isinvisible_alt("/var") true ``` --- src/utils/darwin.jl | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/utils/darwin.jl b/src/utils/darwin.jl index 3a2c940..3850cb4 100644 --- a/src/utils/darwin.jl +++ b/src/utils/darwin.jl @@ -196,3 +196,55 @@ function _string_from_cf_string(cfstr::Cstring, encoding::Unsigned = CF_STRING_E return String(take!(cfio)) end +#===============================================# + +# https://developer.apple.com/documentation/coreservices/lsiteminfoflags/klsiteminfoisinvisible +const KLS_ITEM_INFO_IS_INVISIBLE = 0x00000040 +# https://developer.apple.com/documentation/coreservices/1429609-anonymous/kisinvisible +const K_IS_INVISIBLE = 0x00000040 + +# https://developer.apple.com/documentation/corefoundation/cfurlpathstyle +const K_CF_URL_POSIX_PATH_STYLE = zero(Int8) + +# https://developer.apple.com/documentation/corefoundation/1543250-cfurlcreatewithfilesystempath +function _cf_url_create_with_file_system_path(cfstr::Cstring, is_directory::Bool, path_style::Integer = K_CF_URL_POSIX_PATH_STYLE) + # CFURLRef CFURLCreateWithFileSystemPath(CFAllocatorRef allocator, CFStringRef filePath, CFURLPathStyle pathStyle, Boolean isDirectory); + url_ref = ccall(:CFURLCreateWithFileSystemPath, Ptr{UInt32}, + (Ptr{Cvoid}, Cstring, Int32, Bool), + C_NULL, cfstr, path_style, is_directory) + return url_ref +end +# _cf_url_create_with_file_system_path(f::AbstractString, path_style::Integer = K_CF_URL_POSIX_PATH_STYLE, str_encoding::Unsigned = CF_STRING_ENCODING) = +# _cf_url_create_with_file_system_path(_cf_string_create_with_cstring(f, str_encoding), isdir(f), path_style) + + +# https://developer.apple.com/documentation/coreservices/lsiteminforecord +function _ls_item_info_record() + error("not yet implemented") +end + +# https://developer.apple.com/documentation/coreservices/lsrequestedinfo/klsrequestallflags +const K_LS_REQUEST_ALL_FLAGS = 0x00000010 + +# https://developer.apple.com/documentation/coreservices/1445685-lscopyiteminfoforurl +function _ls_copy_item_info_for_url(url_ref::Ptr{UInt32}, requested_info::Unsigned = K_LS_REQUEST_ALL_FLAGS) + # buf = Vector{UInt32}(undef, 100) + buf = zeros(UInt32, 100) + # OSStatus LSCopyItemInfoForURL(CFURLRef inURL, LSRequestedInfo inWhichInfo, LSItemInfoRecord *outItemInfo); + ptr = ccall(:LSCopyItemInfoForURL, Ptr{UInt32}, + (Ptr{UInt32}, UInt32, Ptr{Cvoid}), + url_ref, requested_info, buf) + return buf +end + +# https://developer.apple.com/documentation/coreservices/lsiteminfoflags +function _ls_item_info_flags() + error("not yet implemented") +end + +function _isinvisible_alt(f::AbstractString, str_encoding::Unsigned = CF_STRING_ENCODING, path_style::Integer = K_CF_URL_POSIX_PATH_STYLE) + cfstr = _cfstring_create_with_cstring(f, str_encoding) + url_ref = _cf_url_create_with_file_system_path(cfstr, isdir(f)) + item_info = _ls_copy_item_info_for_url(url_ref, K_IS_INVISIBLE) + return !iszero(item_info[1] & K_IS_INVISIBLE) +end From d364ce14b6b258ec9ca80010f002d9cbbd707598 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 26 Sep 2022 16:10:58 +1300 Subject: [PATCH 02/10] Add deprecation warnings for some Obj-C calls --- src/utils/darwin.jl | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/utils/darwin.jl b/src/utils/darwin.jl index 3850cb4..827ec43 100644 --- a/src/utils/darwin.jl +++ b/src/utils/darwin.jl @@ -199,7 +199,9 @@ end #===============================================# # https://developer.apple.com/documentation/coreservices/lsiteminfoflags/klsiteminfoisinvisible +# TODO: convert this to enum: https://developer.apple.com/documentation/coreservices/lsiteminfoflags: https://github.com/phracker/MacOSX-SDKs/blob/041600eda65c6a668f66cb7d56b7d1da3e8bcc93/MacOSX10.6.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Headers/LSInfo.h#L95-L111 const KLS_ITEM_INFO_IS_INVISIBLE = 0x00000040 + # https://developer.apple.com/documentation/coreservices/1429609-anonymous/kisinvisible const K_IS_INVISIBLE = 0x00000040 @@ -208,26 +210,30 @@ const K_CF_URL_POSIX_PATH_STYLE = zero(Int8) # https://developer.apple.com/documentation/corefoundation/1543250-cfurlcreatewithfilesystempath function _cf_url_create_with_file_system_path(cfstr::Cstring, is_directory::Bool, path_style::Integer = K_CF_URL_POSIX_PATH_STYLE) + # TODO: handle error codes # CFURLRef CFURLCreateWithFileSystemPath(CFAllocatorRef allocator, CFStringRef filePath, CFURLPathStyle pathStyle, Boolean isDirectory); url_ref = ccall(:CFURLCreateWithFileSystemPath, Ptr{UInt32}, (Ptr{Cvoid}, Cstring, Int32, Bool), C_NULL, cfstr, path_style, is_directory) return url_ref end -# _cf_url_create_with_file_system_path(f::AbstractString, path_style::Integer = K_CF_URL_POSIX_PATH_STYLE, str_encoding::Unsigned = CF_STRING_ENCODING) = -# _cf_url_create_with_file_system_path(_cf_string_create_with_cstring(f, str_encoding), isdir(f), path_style) - # https://developer.apple.com/documentation/coreservices/lsiteminforecord function _ls_item_info_record() + @warn "LSItemInfoRecord has been deprecated since macOS 10.11" error("not yet implemented") end # https://developer.apple.com/documentation/coreservices/lsrequestedinfo/klsrequestallflags const K_LS_REQUEST_ALL_FLAGS = 0x00000010 +# TODO: convert this to enum: https://developer.apple.com/documentation/coreservices/lsrequestedinfo: https://github.com/phracker/MacOSX-SDKs/blob/041600eda65c6a668f66cb7d56b7d1da3e8bcc93/MacOSX10.6.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Headers/LSInfo.h#L83-L93 # https://developer.apple.com/documentation/coreservices/1445685-lscopyiteminfoforurl function _ls_copy_item_info_for_url(url_ref::Ptr{UInt32}, requested_info::Unsigned = K_LS_REQUEST_ALL_FLAGS) + # TODO: handle error codes + requested_info == K_LS_REQUEST_ALL_FLAGS && @warn "kLSRequestAllFlags has been deprecated since macOS 10.11" + requested_info == KLS_ITEM_INFO_IS_INVISIBLE && @warn "kLSItemInfoIsInvisible has been deprecated since macOS 10.11; ensure you are using kIsInvisible instead" + @warn "LSCopyItemInfoForURL has been deprecated since macOS 10.11" # buf = Vector{UInt32}(undef, 100) buf = zeros(UInt32, 100) # OSStatus LSCopyItemInfoForURL(CFURLRef inURL, LSRequestedInfo inWhichInfo, LSItemInfoRecord *outItemInfo); @@ -237,11 +243,6 @@ function _ls_copy_item_info_for_url(url_ref::Ptr{UInt32}, requested_info::Unsign return buf end -# https://developer.apple.com/documentation/coreservices/lsiteminfoflags -function _ls_item_info_flags() - error("not yet implemented") -end - function _isinvisible_alt(f::AbstractString, str_encoding::Unsigned = CF_STRING_ENCODING, path_style::Integer = K_CF_URL_POSIX_PATH_STYLE) cfstr = _cfstring_create_with_cstring(f, str_encoding) url_ref = _cf_url_create_with_file_system_path(cfstr, isdir(f)) From 9794c3db45efe3016a36802677f69a9c98ac515c Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 26 Sep 2022 16:11:47 +1300 Subject: [PATCH 03/10] Add tests for new _isinvisiible function --- test/runtests.jl | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 427de09..e067e33 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -25,11 +25,26 @@ using Test # Case 2: UNIX-specific directories # TODO: complete this case - @test HiddenFiles.ishidden("/bin/") - @test HiddenFiles.ishidden("/dev/") - @test HiddenFiles.ishidden("/usr/") - @test !HiddenFiles.ishidden("/tmp/") - + @test HiddenFiles.ishidden("/bin") + @test HiddenFiles.ishidden("/dev") + @test HiddenFiles.ishidden("/dev") + @test HiddenFiles.ishidden("/etc") + @test HiddenFiles.ishidden("/sbin") + @test HiddenFiles.ishidden("/sbin") + @test HiddenFiles.ishidden("/tmp") + @test HiddenFiles.ishidden("/usr") + @test HiddenFiles.ishidden("/var") + @test HiddenFiles._isinvisible_alt("/bin") + @test HiddenFiles._isinvisible_alt("/dev") + @test HiddenFiles._isinvisible_alt("/dev") + @test HiddenFiles._isinvisible_alt("/etc") + @test HiddenFiles._isinvisible_alt("/sbin") + @test HiddenFiles._isinvisible_alt("/sbin") + @test HiddenFiles._isinvisible_alt("/tmp") + @test HiddenFiles._isinvisible_alt("/usr") + @test HiddenFiles._isinvisible_alt("/var") + @test !HiddenFiles._isinvisible_alt("/bin/bash") + # Case 3: Explicitly hidden files and directories @test HiddenFiles._isinvisible("/Volumes") @test ishidden("/Volumes") @@ -41,7 +56,8 @@ using Test @test ishidden("/System/Applications/Utilities/Terminal.app/Contents/") # This should be the same as above, as we expand all paths using realpath @test !HiddenFiles._ispackage_or_bundle("/System/Applications/Utilities/Terminal.app/Contents/") @test HiddenFiles._exists_inside_package_or_bundle("/System/Applications/Utilities/Terminal.app/Contents/") - @test !HiddenFiles._exists_inside_package_or_bundle("/bin/") + @test !HiddenFiles._exists_inside_package_or_bundle("/bin") + @test !HiddenFiles._exists_inside_package_or_bundle("/tmp") f = String(rand(Char, 32)) # this path shouldn't exist cfstr_nonexistent = HiddenFiles._cfstring_create_with_cstring(f) @test_throws Exception HiddenFiles._mditem_create(cfstr_nonexistent) From 54ced37c9f8f59674e0da4e581e5938a735a68f9 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 26 Sep 2022 16:27:55 +1300 Subject: [PATCH 04/10] Move macOS _isinvisible function to main file; correct tests Moved _isinvisible_alt to main module file, and renamed to _isinvisible_macos_item_info, and corrected tests accordingly. Currently tests are failing because `realpath` expands some directories (e.g., `/tmp`) to `/private/tmp`. I should perhaps use `normpath` instead of `realpath`. --- src/HiddenFiles.jl | 21 +++++++++++++++------ src/utils/darwin.jl | 7 +------ test/runtests.jl | 28 ++++++++++++++-------------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/HiddenFiles.jl b/src/HiddenFiles.jl index 0bfe883..33ca853 100644 --- a/src/HiddenFiles.jl +++ b/src/HiddenFiles.jl @@ -58,9 +58,9 @@ include("docs.jl") # https://github.com/dotnet/runtime/blob/5992145db2cb57956ee444aa0f0c2f3f85ee3673/src/native/libs/System.Native/pal_io.c#L219 # https://github.com/davidkaya/corefx/blob/4fd3d39f831f3e14f311b0cdc0a33d662e684a9c/src/System.IO.FileSystem/src/System/IO/FileStatus.Unix.cs#L88 - _isinvisible(f::AbstractString) = (_st_flags(f) & UF_HIDDEN) == UF_HIDDEN + _isinvisible_st_flags(f::AbstractString) = (_st_flags(f) & UF_HIDDEN) == UF_HIDDEN - _ishidden_bsd_related(f::AbstractString) = _ishidden_unix(f) || _isinvisible(f) + _ishidden_bsd_related(f::AbstractString) = _ishidden_unix(f) || _isinvisible_st_flags(f) end @static if Sys.isapple() # macOS/Darwin @@ -86,15 +86,24 @@ include("docs.jl") # - `/tmp`—Contains temporary files created by apps and the system. # - `/usr`—Contains non-essential command-line binaries, libraries, header files, and other data. # - `/var`—Contains log files and other files whose content is variable. (Log files are typically viewed using the Console app.) - # TODO - _issystemfile(f::AbstractString) = false + _issystemdir(f::AbstractString) = false # TODO + + # This _isinvisible function seems to capture some cases (e.g., `/tmp`) that the other _isinvisible function does not + function _isinvisible_macos_item_info(f::AbstractString, str_encoding::Unsigned = CF_STRING_ENCODING, path_style::Integer = K_CF_URL_POSIX_PATH_STYLE) + cfstr = _cfstring_create_with_cstring(f, str_encoding) + url_ref = _cf_url_create_with_file_system_path(cfstr, isdir(f)) + item_info = _ls_copy_item_info_for_url(url_ref, K_IS_INVISIBLE) + return !iszero(item_info[1] & K_IS_INVISIBLE) + end #=== Case 3: Explicitly hidden files and directories ===# # The Finder may hide specific files or directories that should not be accessed directly by the user. The most notable example of # this is the /Volumes directory, which contains a subdirectory for each mounted disk in the local file system from the command line. # (The Finder provides a different user interface for accessing local disks.) In macOS 10.7 and later, the Finder also hides the - # `~/Library` directory—that is, the `Library` directory located in the user’s home directory. This case is handled by `_isinvisible`. + # `~/Library` directory—that is, the `Library` directory located in the user’s home directory. + # + # This case is handled by `_isinvisible_st_flags`. #=== Case 4: Packages and bundles ===# @@ -149,7 +158,7 @@ include("docs.jl") #=== All macOS cases ===# - _ishidden_macos(f::AbstractString) = _ishidden_bsd_related(f) || _issystemfile(f) || _exists_inside_package_or_bundle(f) + _ishidden_macos(f::AbstractString) = _ishidden_bsd_related(f) || _issystemdir(f) || _isinvisible_macos_item_info(f) || _exists_inside_package_or_bundle(f) _ishidden = _ishidden_macos elseif Sys.isbsd() # BSD; this excludes macOS through control flow (as macOS is checked for first) _ishidden_bsd(f::AbstractString) = _ishidden_bsd_related(f) diff --git a/src/utils/darwin.jl b/src/utils/darwin.jl index 827ec43..ca07321 100644 --- a/src/utils/darwin.jl +++ b/src/utils/darwin.jl @@ -243,9 +243,4 @@ function _ls_copy_item_info_for_url(url_ref::Ptr{UInt32}, requested_info::Unsign return buf end -function _isinvisible_alt(f::AbstractString, str_encoding::Unsigned = CF_STRING_ENCODING, path_style::Integer = K_CF_URL_POSIX_PATH_STYLE) - cfstr = _cfstring_create_with_cstring(f, str_encoding) - url_ref = _cf_url_create_with_file_system_path(cfstr, isdir(f)) - item_info = _ls_copy_item_info_for_url(url_ref, K_IS_INVISIBLE) - return !iszero(item_info[1] & K_IS_INVISIBLE) -end + diff --git a/test/runtests.jl b/test/runtests.jl index e067e33..4d7009f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -34,21 +34,21 @@ using Test @test HiddenFiles.ishidden("/tmp") @test HiddenFiles.ishidden("/usr") @test HiddenFiles.ishidden("/var") - @test HiddenFiles._isinvisible_alt("/bin") - @test HiddenFiles._isinvisible_alt("/dev") - @test HiddenFiles._isinvisible_alt("/dev") - @test HiddenFiles._isinvisible_alt("/etc") - @test HiddenFiles._isinvisible_alt("/sbin") - @test HiddenFiles._isinvisible_alt("/sbin") - @test HiddenFiles._isinvisible_alt("/tmp") - @test HiddenFiles._isinvisible_alt("/usr") - @test HiddenFiles._isinvisible_alt("/var") - @test !HiddenFiles._isinvisible_alt("/bin/bash") + @test HiddenFiles._isinvisible_macos_item_info("/bin") + @test HiddenFiles._isinvisible_macos_item_info("/dev") + @test HiddenFiles._isinvisible_macos_item_info("/dev") + @test HiddenFiles._isinvisible_macos_item_info("/etc") + @test HiddenFiles._isinvisible_macos_item_info("/sbin") + @test HiddenFiles._isinvisible_macos_item_info("/sbin") + @test HiddenFiles._isinvisible_macos_item_info("/tmp") + @test HiddenFiles._isinvisible_macos_item_info("/usr") + @test HiddenFiles._isinvisible_macos_item_info("/var") + @test !HiddenFiles._isinvisible_macos_item_info("/bin/bash") # Case 3: Explicitly hidden files and directories - @test HiddenFiles._isinvisible("/Volumes") + @test HiddenFiles._isinvisible_st_flags("/Volumes") @test ishidden("/Volumes") - @test !HiddenFiles._isinvisible(p′) + @test !HiddenFiles._isinvisible_st_flags(p′) # Case 4: Packages and bundles @test !ishidden("/System/Applications/Utilities/Terminal.app") @@ -72,9 +72,9 @@ using Test # TODO: should we not only support FreeBSD? Are we testing on other BSD systems? OpenBSD? @testset "HiddenFiles.jl—FreeBSD" begin @test ishidden(p) - @test !HiddenFiles._isinvisible(p) + @test !HiddenFiles._isinvisible_st_flags(p) @test ishidden(p′) - @test !HiddenFiles._isinvisible(p′) + @test !HiddenFiles._isinvisible_st_flags(p′) @test !ishidden(homedir()) @test !ishidden("/bin/") @test !ishidden("/dev/") From fde99f668820b50a514a69706717e8cf1304fd07 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Fri, 20 Jun 2025 15:03:59 +0900 Subject: [PATCH 05/10] Add test for handling of /private --- test/runtests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 5dd4f1d..68d3ac5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -34,8 +34,8 @@ using Test @test HiddenFiles.ishidden("/etc") @test HiddenFiles.ishidden("/sbin") @test HiddenFiles.ishidden("/sbin") - @test HiddenFiles.ishidden("/tmp") - # @test !HiddenFiles.ishidden("/tmp/") # Is this hidden or not? See ec15fd77 + @test HiddenFiles.ishidden("/tmp") # This expands to /private/tmp, but /private is hidden which means /tmp should also be hidden (see 54ced37c) + @test HiddenFiles.ishidden("/private") @test HiddenFiles.ishidden("/usr") @test HiddenFiles.ishidden("/var") @test HiddenFiles._isinvisible_macos_item_info("/bin") From ceeb02e09dfc4c7322ea18c4f45980ae3bd303e1 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Fri, 20 Jun 2025 15:04:45 +0900 Subject: [PATCH 06/10] Correct value of KS_IS_INVISIBLE Accidentally made it the same value as (the deprecated) value KLS_ITEM_INFO_IS_INVISIBLE. --- src/utils/darwin.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/darwin.jl b/src/utils/darwin.jl index ea8b2c1..16c4cbc 100644 --- a/src/utils/darwin.jl +++ b/src/utils/darwin.jl @@ -218,7 +218,7 @@ end const KLS_ITEM_INFO_IS_INVISIBLE = 0x00000040 # https://developer.apple.com/documentation/coreservices/1429609-anonymous/kisinvisible -const K_IS_INVISIBLE = 0x00000040 +const K_IS_INVISIBLE = 0x4000 # https://developer.apple.com/documentation/corefoundation/cfurlpathstyle const K_CF_URL_POSIX_PATH_STYLE = zero(Int8) From 4e575a2adbbc5d13fa292c1455332f9a89fa916f Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Fri, 20 Jun 2025 15:17:50 +0900 Subject: [PATCH 07/10] Add note to consider using ObjectiveC.jl I think this package came out in 2014 6f46bde - initial empty commit (Wed 15 Oct 2014) <@MikeInnes> But it wasn't working on Julia till Tim picked it up in 2024 91eda41 - Replace REQUIRE with Project.toml. (Tue 28 Feb 2023) <@maleadt> Which is *after* my initial work on HiddenFiles.jl 243ee48 - Initial commit (Wed 24 Aug 2022) <@jakewilliami> I think its current state would be easier to work with. See #8 --- src/utils/darwin.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/darwin.jl b/src/utils/darwin.jl index 16c4cbc..8155b82 100644 --- a/src/utils/darwin.jl +++ b/src/utils/darwin.jl @@ -1,3 +1,7 @@ +# TODO: consider using ObjectiveC.jl (HiddenFiles.jl#8) +# https://discourse.julialang.org/t/95862 +# https://github.com/JuliaInterop/ObjectiveC.jl + # https://opensource.apple.com/source/CF/CF-635/CFString.h.auto.html # https://developer.apple.com/documentation/corefoundation/cfstringbuiltinencodings const K_CF_STRING_ENCODING_MAC_ROMAN = 0x0 From 85b365b7ff8ba15857cedf1c0aa731113f9ecb5f Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Fri, 20 Jun 2025 16:35:37 +0900 Subject: [PATCH 08/10] Store stat buffer in struct Stat was behaving stangely (i.e., differently given /tmp and its real path (see 54ced37c)). In order to remove one thing from the equation (i.e., getting the offset wrong), I have moved the output of stat into its own struct, allowing me to directly access the fields I need. Closes #14 --- src/HiddenFiles.jl | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/HiddenFiles.jl b/src/HiddenFiles.jl index ed2582a..c5b9753 100644 --- a/src/HiddenFiles.jl +++ b/src/HiddenFiles.jl @@ -55,19 +55,49 @@ include("path.jl") # https://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=2 const UF_HIDDEN = 0x00008000 + struct BSDTimeSpec + sec::Int64 + nsec::Int64 + end + + # See HiddenFiles.jl#14 + struct BSDStatStruct + st_dev::UInt64 + st_mode::UInt64 + st_nlink::UInt64 + st_uid::UInt64 + st_gid::UInt64 + st_rdev::UInt64 + st_ino::UInt64 + st_size::UInt64 + st_blksize::UInt64 + st_blocks::UInt64 + st_flags::UInt64 + st_gen::UInt64 + st_atime::BSDTimeSpec + st_mtim::BSDTimeSpec + st_ctim::BSDTimeSpec + st_birthtim::BSDTimeSpec + + # https://discourse.julialang.org/t/106893/6 + # https://discourse.julialang.org/t/75835/6 + # BSDStatStruct() = new() + end + # https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/stat.2.html # http://docs.libuv.org/en/v1.x/fs.html#c.uv_stat_t - const ST_FLAGS_STAT_OFFSET = 0x15 + # https://discourse.julialang.org/t/75835/5 + # + # See previous version of _st_flags at f149f1a function _st_flags(f::AbstractString) - statbuf = Vector{UInt32}(undef, ccall(:jl_sizeof_stat, Int32, ())) - + # Note: sizeof(BSDStatStruct) must equal ccall(:jl_sizeof_stat, Int32, ()) + stat_t_ref = Ref{BSDStatStruct}() # int stat(const char *restrict path, struct stat *restrict buf); # int stat(const char * restrict path, struct stat * restrict sb); - i = ccall(:jl_stat, Int32, (Cstring, Ptr{Cvoid}), f, statbuf) + i = ccall(:jl_lstat, Cvoid, (Cstring, Ptr{BSDStatStruct}), f, stat_t_ref) iszero(i) || Base.uv_error("_st_flags($(repr(f)))", i) - - # st_flags offset is at index 11, or 21 in 32-bit - return statbuf[ST_FLAGS_STAT_OFFSET] + stat_t = stat_t_ref.x + return stat_t.st_flags end # https://github.com/dotnet/runtime/blob/5992145db2cb57956ee444aa0f0c2f3f85ee3673/src/native/libs/System.Native/pal_io.c#L219 From 56ed7d605271562d0723811b833106244b98aec2 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Fri, 20 Jun 2025 16:39:17 +0900 Subject: [PATCH 09/10] Add additional tests for hidden tmp dir on BSD --- test/runtests.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 68d3ac5..62962d4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -36,6 +36,9 @@ using Test @test HiddenFiles.ishidden("/sbin") @test HiddenFiles.ishidden("/tmp") # This expands to /private/tmp, but /private is hidden which means /tmp should also be hidden (see 54ced37c) @test HiddenFiles.ishidden("/private") + @test HiddenFiles.ishidden("/private/tmp") + @test HiddenFiles.ishidden("/private/tmp/") + @test HiddenFiles.ishidden("/tmp/") @test HiddenFiles.ishidden("/usr") @test HiddenFiles.ishidden("/var") @test HiddenFiles._isinvisible_macos_item_info("/bin") From db0b62f1aa449eb3dfcfa0786e444abf38865280 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Fri, 20 Jun 2025 16:49:13 +0900 Subject: [PATCH 10/10] Fix error in return type check for st flags --- src/HiddenFiles.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HiddenFiles.jl b/src/HiddenFiles.jl index c5b9753..d48faab 100644 --- a/src/HiddenFiles.jl +++ b/src/HiddenFiles.jl @@ -94,7 +94,7 @@ include("path.jl") stat_t_ref = Ref{BSDStatStruct}() # int stat(const char *restrict path, struct stat *restrict buf); # int stat(const char * restrict path, struct stat * restrict sb); - i = ccall(:jl_lstat, Cvoid, (Cstring, Ptr{BSDStatStruct}), f, stat_t_ref) + i = ccall(:jl_lstat, Int32, (Cstring, Ptr{BSDStatStruct}), f, stat_t_ref) iszero(i) || Base.uv_error("_st_flags($(repr(f)))", i) stat_t = stat_t_ref.x return stat_t.st_flags