logo

oasis-root

Compiled tree of Oasis Linux based on own branch at <https://hacktivis.me/git/oasis/> git clone https://anongit.hacktivis.me/git/oasis-root.git

dyld.py (5283B)


  1. """
  2. dyld emulation
  3. """
  4. import os
  5. from ctypes.macholib.framework import framework_info
  6. from ctypes.macholib.dylib import dylib_info
  7. from itertools import *
  8. try:
  9. from _ctypes import _dyld_shared_cache_contains_path
  10. except ImportError:
  11. def _dyld_shared_cache_contains_path(*args):
  12. raise NotImplementedError
  13. __all__ = [
  14. 'dyld_find', 'framework_find',
  15. 'framework_info', 'dylib_info',
  16. ]
  17. # These are the defaults as per man dyld(1)
  18. #
  19. DEFAULT_FRAMEWORK_FALLBACK = [
  20. os.path.expanduser("~/Library/Frameworks"),
  21. "/Library/Frameworks",
  22. "/Network/Library/Frameworks",
  23. "/System/Library/Frameworks",
  24. ]
  25. DEFAULT_LIBRARY_FALLBACK = [
  26. os.path.expanduser("~/lib"),
  27. "/usr/local/lib",
  28. "/lib",
  29. "/usr/lib",
  30. ]
  31. def dyld_env(env, var):
  32. if env is None:
  33. env = os.environ
  34. rval = env.get(var)
  35. if rval is None:
  36. return []
  37. return rval.split(':')
  38. def dyld_image_suffix(env=None):
  39. if env is None:
  40. env = os.environ
  41. return env.get('DYLD_IMAGE_SUFFIX')
  42. def dyld_framework_path(env=None):
  43. return dyld_env(env, 'DYLD_FRAMEWORK_PATH')
  44. def dyld_library_path(env=None):
  45. return dyld_env(env, 'DYLD_LIBRARY_PATH')
  46. def dyld_fallback_framework_path(env=None):
  47. return dyld_env(env, 'DYLD_FALLBACK_FRAMEWORK_PATH')
  48. def dyld_fallback_library_path(env=None):
  49. return dyld_env(env, 'DYLD_FALLBACK_LIBRARY_PATH')
  50. def dyld_image_suffix_search(iterator, env=None):
  51. """For a potential path iterator, add DYLD_IMAGE_SUFFIX semantics"""
  52. suffix = dyld_image_suffix(env)
  53. if suffix is None:
  54. return iterator
  55. def _inject(iterator=iterator, suffix=suffix):
  56. for path in iterator:
  57. if path.endswith('.dylib'):
  58. yield path[:-len('.dylib')] + suffix + '.dylib'
  59. else:
  60. yield path + suffix
  61. yield path
  62. return _inject()
  63. def dyld_override_search(name, env=None):
  64. # If DYLD_FRAMEWORK_PATH is set and this dylib_name is a
  65. # framework name, use the first file that exists in the framework
  66. # path if any. If there is none go on to search the DYLD_LIBRARY_PATH
  67. # if any.
  68. framework = framework_info(name)
  69. if framework is not None:
  70. for path in dyld_framework_path(env):
  71. yield os.path.join(path, framework['name'])
  72. # If DYLD_LIBRARY_PATH is set then use the first file that exists
  73. # in the path. If none use the original name.
  74. for path in dyld_library_path(env):
  75. yield os.path.join(path, os.path.basename(name))
  76. def dyld_executable_path_search(name, executable_path=None):
  77. # If we haven't done any searching and found a library and the
  78. # dylib_name starts with "@executable_path/" then construct the
  79. # library name.
  80. if name.startswith('@executable_path/') and executable_path is not None:
  81. yield os.path.join(executable_path, name[len('@executable_path/'):])
  82. def dyld_default_search(name, env=None):
  83. yield name
  84. framework = framework_info(name)
  85. if framework is not None:
  86. fallback_framework_path = dyld_fallback_framework_path(env)
  87. for path in fallback_framework_path:
  88. yield os.path.join(path, framework['name'])
  89. fallback_library_path = dyld_fallback_library_path(env)
  90. for path in fallback_library_path:
  91. yield os.path.join(path, os.path.basename(name))
  92. if framework is not None and not fallback_framework_path:
  93. for path in DEFAULT_FRAMEWORK_FALLBACK:
  94. yield os.path.join(path, framework['name'])
  95. if not fallback_library_path:
  96. for path in DEFAULT_LIBRARY_FALLBACK:
  97. yield os.path.join(path, os.path.basename(name))
  98. def dyld_find(name, executable_path=None, env=None):
  99. """
  100. Find a library or framework using dyld semantics
  101. """
  102. for path in dyld_image_suffix_search(chain(
  103. dyld_override_search(name, env),
  104. dyld_executable_path_search(name, executable_path),
  105. dyld_default_search(name, env),
  106. ), env):
  107. if os.path.isfile(path):
  108. return path
  109. try:
  110. if _dyld_shared_cache_contains_path(path):
  111. return path
  112. except NotImplementedError:
  113. pass
  114. raise ValueError("dylib %s could not be found" % (name,))
  115. def framework_find(fn, executable_path=None, env=None):
  116. """
  117. Find a framework using dyld semantics in a very loose manner.
  118. Will take input such as:
  119. Python
  120. Python.framework
  121. Python.framework/Versions/Current
  122. """
  123. error = None
  124. try:
  125. return dyld_find(fn, executable_path=executable_path, env=env)
  126. except ValueError as e:
  127. error = e
  128. fmwk_index = fn.rfind('.framework')
  129. if fmwk_index == -1:
  130. fmwk_index = len(fn)
  131. fn += '.framework'
  132. fn = os.path.join(fn, os.path.basename(fn[:fmwk_index]))
  133. try:
  134. return dyld_find(fn, executable_path=executable_path, env=env)
  135. except ValueError:
  136. raise error
  137. finally:
  138. error = None
  139. def test_dyld_find():
  140. env = {}
  141. assert dyld_find('libSystem.dylib') == '/usr/lib/libSystem.dylib'
  142. assert dyld_find('System.framework/System') == '/System/Library/Frameworks/System.framework/System'
  143. if __name__ == '__main__':
  144. test_dyld_find()