@@ -7,21 +7,201 @@ module OS
77 module Mac
88 # Wrapping module for FFI calls to system libraries.
99 module FFI
10- sig { returns ( Fiddle ::Handle ) }
11- private_class_method def self . libsystem
12- @libsystem ||= T . let ( Fiddle . dlopen ( "/usr/lib/libSystem.B.dylib" ) , T . nilable ( Fiddle ::Handle ) )
10+ # NativeLibrary provides helper methods for loading system libraries and accessing functions and constants.
11+ # Functions and constants are cached so they only need to be looked up once.
12+ module NativeLibrary
13+ private
14+
15+ sig { params ( path : String ) . void }
16+ def use_library ( path )
17+ @library_path = T . let ( path . freeze , T . nilable ( String ) )
18+ end
19+
20+ sig { returns ( Fiddle ::Handle ) }
21+ def handle
22+ @handle ||= T . let ( Fiddle . dlopen ( T . must ( @library_path ) ) , T . nilable ( Fiddle ::Handle ) )
23+ end
24+
25+ sig { params ( name : String , argument_types : T ::Array [ Integer ] , return_type : Integer ) . returns ( Fiddle ::Function ) }
26+ def function ( name , argument_types , return_type )
27+ @functions ||= T . let ( { } , T . nilable ( T ::Hash [ String , Fiddle ::Function ] ) )
28+ @functions [ name ] ||= Fiddle ::Function . new ( handle [ name ] , argument_types , return_type )
29+ end
30+
31+ sig { params ( name : String , dereference : T ::Boolean ) . returns ( Fiddle ::Pointer ) }
32+ def constant ( name , dereference : false )
33+ @constants ||= T . let ( { } , T . nilable ( T ::Hash [ [ String , T ::Boolean ] , Fiddle ::Pointer ] ) )
34+ @constants [ [ name , dereference ] ] ||= begin
35+ pointer = Fiddle ::Pointer . new ( handle [ name ] )
36+ dereference ? pointer . ptr : pointer
37+ end
38+ end
1339 end
1440
41+ extend NativeLibrary
42+
43+ use_library "/usr/lib/libSystem.B.dylib"
44+
45+ # mach-o/dyld.h:
46+ # bool _dyld_shared_cache_contains_path(const char* path);
1547 sig { params ( path : String ) . returns ( T ::Boolean ) }
1648 def self . dyld_shared_cache_contains_path ( path )
17- @dyld_shared_cache_contains_path ||= T . let (
18- Fiddle ::Function . new (
19- libsystem [ "_dyld_shared_cache_contains_path" ] ,
20- [ Fiddle ::TYPE_CONST_STRING ] ,
49+ function (
50+ "_dyld_shared_cache_contains_path" ,
51+ [ Fiddle ::TYPE_CONST_STRING ] ,
52+ Fiddle ::TYPE_BOOL ,
53+ ) . call ( path )
54+ end
55+
56+ # CoreFoundation.framework wrapper
57+ module CoreFoundation
58+ extend NativeLibrary
59+
60+ use_library "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
61+
62+ sig { params ( ptr : Fiddle ::Pointer ) . returns ( Fiddle ::Pointer ) }
63+ private_class_method def self . autorelease ( ptr )
64+ return ptr if ptr . null?
65+
66+ # CoreFoundation/CFBase.h:
67+ # void CFRelease(CFTypeRef cf);
68+ ptr . free = function ( "CFRelease" , [ Fiddle ::TYPE_VOIDP ] , Fiddle ::TYPE_VOID )
69+ ptr
70+ end
71+
72+ # CoreFoundation/CFDictionary.h:
73+ # extern const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks;
74+ sig { returns ( Fiddle ::Pointer ) }
75+ def self . type_dictionary_key_call_backs = constant ( "kCFTypeDictionaryKeyCallBacks" )
76+
77+ # CoreFoundation/CFDictionary.h:
78+ # extern const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks
79+ sig { returns ( Fiddle ::Pointer ) }
80+ def self . type_dictionary_value_call_backs = constant ( "kCFTypeDictionaryValueCallBacks" )
81+
82+ # CoreFoundation/CFURL.h:
83+ # extern const CFStringRef kCFURLQuarantinePropertiesKey;
84+ sig { returns ( Fiddle ::Pointer ) }
85+ def self . url_quarantine_properties_key = constant ( "kCFURLQuarantinePropertiesKey" , dereference : true )
86+
87+ # CoreFoundation/CFString.h:
88+ # CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding);
89+ sig { params ( string : String ) . returns ( Fiddle ::Pointer ) }
90+ def self . string_create ( string )
91+ cf_encoding = case string . encoding
92+ when Encoding ::UTF_8
93+ 0x08000100 # kCFStringEncodingUTF8
94+ when Encoding ::US_ASCII
95+ 0x0600 # kCFStringEncodingASCII
96+ when Encoding ::ASCII_8BIT , Encoding ::ISO8859_1
97+ # ASCII-8BIT could be anything, so just use Latin-1
98+ 0x0201 # kCFStringEncodingISOLatin1
99+ else
100+ # Try convert to UTF-8 and move on
101+ string = string . encode ( Encoding ::UTF_8 )
102+ 0x08000100
103+ end
104+
105+ autorelease (
106+ function (
107+ "CFStringCreateWithCString" ,
108+ [ Fiddle ::TYPE_VOIDP , Fiddle ::TYPE_CONST_STRING , Fiddle ::TYPE_UINT32_T ] ,
109+ Fiddle ::TYPE_VOIDP ,
110+ ) . call ( nil , string , cf_encoding ) ,
111+ )
112+ end
113+
114+ # CoreFoundation/CFDictionary.h:
115+ # CFDictionaryRef CFDictionaryCreate(
116+ # CFAllocatorRef allocator,
117+ # const void **keys,
118+ # const void **values,
119+ # CFIndex numValues,
120+ # const CFDictionaryKeyCallBacks *keyCallBacks,
121+ # const CFDictionaryValueCallBacks *valueCallBacks);
122+ sig { params ( hash : T ::Hash [ Fiddle ::Pointer , Fiddle ::Pointer ] ) . returns ( Fiddle ::Pointer ) }
123+ def self . dictionary_create ( hash )
124+ size = Fiddle ::SIZEOF_VOIDP * hash . size
125+ Fiddle ::Pointer . malloc ( size , Fiddle ::RUBY_FREE ) do |keys |
126+ Fiddle ::Pointer . malloc ( size , Fiddle ::RUBY_FREE ) do |values |
127+ # Convert array of pointers to continous stream of pointers in the C buffer
128+ keys [ 0 , size ] = hash . keys . pack ( "J*" )
129+ values [ 0 , size ] = hash . values . pack ( "J*" )
130+ return autorelease (
131+ function (
132+ "CFDictionaryCreate" ,
133+ [
134+ Fiddle ::TYPE_VOIDP , Fiddle ::TYPE_VOIDP , Fiddle ::TYPE_VOIDP ,
135+ Fiddle ::TYPE_LONG , Fiddle ::TYPE_VOIDP , Fiddle ::TYPE_VOIDP
136+ ] ,
137+ Fiddle ::TYPE_VOIDP ,
138+ ) . call (
139+ nil , keys , values , hash . size , type_dictionary_key_call_backs , type_dictionary_value_call_backs
140+ ) ,
141+ )
142+ end
143+ end
144+ end
145+
146+ # CoreFoundation/CFURL.h:
147+ # CFURLRef CFURLCreateWithFileSystemPath(CFAllocatorRef allocator,
148+ # CFStringRef filePath, CFURLPathStyle pathStyle, Boolean isDirectory);
149+ sig { params ( path : Fiddle ::Pointer ) . returns ( Fiddle ::Pointer ) }
150+ def self . url_create_with_file_system_path ( path )
151+ autorelease (
152+ function (
153+ "CFURLCreateWithFileSystemPath" ,
154+ [ Fiddle ::TYPE_VOIDP , Fiddle ::TYPE_VOIDP , Fiddle ::TYPE_LONG , Fiddle ::TYPE_BOOL ] ,
155+ Fiddle ::TYPE_VOIDP ,
156+ ) . call ( nil , path , 0 , false ) ,
157+ )
158+ end
159+
160+ # CoreFoundation/CFURL.h:
161+ # Boolean CFURLSetResourcePropertyForKey(CFURLRef url, CFStringRef key, CFTypeRef value, CFErrorRef *error);
162+ sig { params ( url : Fiddle ::Pointer , key : Fiddle ::Pointer , value : Fiddle ::Pointer ) . returns ( T ::Boolean ) }
163+ def self . url_set_resource_property_for_key ( url , key , value )
164+ function (
165+ "CFURLSetResourcePropertyForKey" ,
166+ [ Fiddle ::TYPE_VOIDP , Fiddle ::TYPE_VOIDP , Fiddle ::TYPE_VOIDP , Fiddle ::TYPE_VOIDP ] ,
21167 Fiddle ::TYPE_BOOL ,
22- ) , T . nilable ( Fiddle ::Function )
168+ ) . call ( url , key , value , nil )
169+ end
170+ end
171+
172+ # LaunchServices.framework wrapper
173+ module LaunchServices
174+ extend NativeLibrary
175+
176+ use_library (
177+ "/System/Library/Frameworks/CoreServices.framework/Versions/A/" \
178+ "Frameworks/LaunchServices.framework/Versions/A/LaunchServices" ,
23179 )
24- @dyld_shared_cache_contains_path . call ( path )
180+
181+ # LaunchServices/LSQuarantine.h:
182+ # extern const CFStringRef kLSQuarantineAgentNameKey;
183+ sig { returns ( Fiddle ::Pointer ) }
184+ def self . quarantine_agent_name_key = constant ( "kLSQuarantineAgentNameKey" , dereference : true )
185+
186+ # LaunchServices/LSQuarantine.h:
187+ # extern const CFStringRef kLSQuarantineTypeKey;
188+ sig { returns ( Fiddle ::Pointer ) }
189+ def self . quarantine_type_key = constant ( "kLSQuarantineTypeKey" , dereference : true )
190+
191+ # LaunchServices/LSQuarantine.h:
192+ # extern const CFStringRef kLSQuarantineTypeWebDownload;
193+ sig { returns ( Fiddle ::Pointer ) }
194+ def self . quarantine_type_web_download = constant ( "kLSQuarantineTypeWebDownload" , dereference : true )
195+
196+ # LaunchServices/LSQuarantine.h:
197+ # extern const CFStringRef kLSQuarantineDataURLKey;
198+ sig { returns ( Fiddle ::Pointer ) }
199+ def self . quarantine_data_url_key = constant ( "kLSQuarantineDataURLKey" , dereference : true )
200+
201+ # LaunchServices/LSQuarantine.h:
202+ # extern const CFStringRef kLSQuarantineOriginURLKey;
203+ sig { returns ( Fiddle ::Pointer ) }
204+ def self . quarantine_origin_url_key = constant ( "kLSQuarantineOriginURLKey" , dereference : true )
25205 end
26206 end
27207 end
0 commit comments