15db71995Sopenharmony_ci/*
25db71995Sopenharmony_ci * Copyright (c) 2021-2022 The Khronos Group Inc.
35db71995Sopenharmony_ci * Copyright (c) 2021-2022 Valve Corporation
45db71995Sopenharmony_ci * Copyright (c) 2021-2022 LunarG, Inc.
55db71995Sopenharmony_ci *
65db71995Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
75db71995Sopenharmony_ci * of this software and/or associated documentation files (the "Materials"), to
85db71995Sopenharmony_ci * deal in the Materials without restriction, including without limitation the
95db71995Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
105db71995Sopenharmony_ci * sell copies of the Materials, and to permit persons to whom the Materials are
115db71995Sopenharmony_ci * furnished to do so, subject to the following conditions:
125db71995Sopenharmony_ci *
135db71995Sopenharmony_ci * The above copyright notice(s) and this permission notice shall be included in
145db71995Sopenharmony_ci * all copies or substantial portions of the Materials.
155db71995Sopenharmony_ci *
165db71995Sopenharmony_ci * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
175db71995Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
185db71995Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
195db71995Sopenharmony_ci *
205db71995Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
215db71995Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
225db71995Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
235db71995Sopenharmony_ci * USE OR OTHER DEALINGS IN THE MATERIALS.
245db71995Sopenharmony_ci *
255db71995Sopenharmony_ci * Author: Charles Giessen <charles@lunarg.com>
265db71995Sopenharmony_ci */
275db71995Sopenharmony_ci
285db71995Sopenharmony_ci#include "shim.h"
295db71995Sopenharmony_ci
305db71995Sopenharmony_ci#include <algorithm>
315db71995Sopenharmony_ci
325db71995Sopenharmony_ci#if defined(__APPLE__)
335db71995Sopenharmony_ci#include <CoreFoundation/CoreFoundation.h>
345db71995Sopenharmony_ci#endif
355db71995Sopenharmony_ci
365db71995Sopenharmony_ciPlatformShim platform_shim;
375db71995Sopenharmony_ciextern "C" {
385db71995Sopenharmony_ci#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__GNU__)
395db71995Sopenharmony_ciPlatformShim* get_platform_shim(std::vector<fs::FolderManager>* folders) {
405db71995Sopenharmony_ci    platform_shim = PlatformShim(folders);
415db71995Sopenharmony_ci    return &platform_shim;
425db71995Sopenharmony_ci}
435db71995Sopenharmony_ci#elif defined(__APPLE__)
445db71995Sopenharmony_ciFRAMEWORK_EXPORT PlatformShim* get_platform_shim(std::vector<fs::FolderManager>* folders) {
455db71995Sopenharmony_ci    platform_shim = PlatformShim(folders);
465db71995Sopenharmony_ci    return &platform_shim;
475db71995Sopenharmony_ci}
485db71995Sopenharmony_ci#endif
495db71995Sopenharmony_ci
505db71995Sopenharmony_ci// Necessary for MacOS function shimming
515db71995Sopenharmony_ci#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__GNU__)
525db71995Sopenharmony_ci#define OPENDIR_FUNC_NAME opendir
535db71995Sopenharmony_ci#define READDIR_FUNC_NAME readdir
545db71995Sopenharmony_ci#define CLOSEDIR_FUNC_NAME closedir
555db71995Sopenharmony_ci#define ACCESS_FUNC_NAME access
565db71995Sopenharmony_ci#define FOPEN_FUNC_NAME fopen
575db71995Sopenharmony_ci#define DLOPEN_FUNC_NAME dlopen
585db71995Sopenharmony_ci#define GETEUID_FUNC_NAME geteuid
595db71995Sopenharmony_ci#define GETEGID_FUNC_NAME getegid
605db71995Sopenharmony_ci#if defined(HAVE_SECURE_GETENV)
615db71995Sopenharmony_ci#define SECURE_GETENV_FUNC_NAME secure_getenv
625db71995Sopenharmony_ci#endif
635db71995Sopenharmony_ci#if defined(HAVE___SECURE_GETENV)
645db71995Sopenharmony_ci#define __SECURE_GETENV_FUNC_NAME __secure_getenv
655db71995Sopenharmony_ci#endif
665db71995Sopenharmony_ci#elif defined(__APPLE__)
675db71995Sopenharmony_ci#define OPENDIR_FUNC_NAME my_opendir
685db71995Sopenharmony_ci#define READDIR_FUNC_NAME my_readdir
695db71995Sopenharmony_ci#define CLOSEDIR_FUNC_NAME my_closedir
705db71995Sopenharmony_ci#define ACCESS_FUNC_NAME my_access
715db71995Sopenharmony_ci#define FOPEN_FUNC_NAME my_fopen
725db71995Sopenharmony_ci#define DLOPEN_FUNC_NAME my_dlopen
735db71995Sopenharmony_ci#define GETEUID_FUNC_NAME my_geteuid
745db71995Sopenharmony_ci#define GETEGID_FUNC_NAME my_getegid
755db71995Sopenharmony_ci#if !defined(TARGET_OS_IPHONE)
765db71995Sopenharmony_ci#if defined(HAVE_SECURE_GETENV)
775db71995Sopenharmony_ci#define SECURE_GETENV_FUNC_NAME my_secure_getenv
785db71995Sopenharmony_ci#endif
795db71995Sopenharmony_ci#if defined(HAVE___SECURE_GETENV)
805db71995Sopenharmony_ci#define __SECURE_GETENV_FUNC_NAME my__secure_getenv
815db71995Sopenharmony_ci#endif
825db71995Sopenharmony_ci#endif
835db71995Sopenharmony_ci#endif
845db71995Sopenharmony_ci
855db71995Sopenharmony_ciusing PFN_OPENDIR = DIR* (*)(const char* path_name);
865db71995Sopenharmony_ciusing PFN_READDIR = struct dirent* (*)(DIR* dir_stream);
875db71995Sopenharmony_ciusing PFN_CLOSEDIR = int (*)(DIR* dir_stream);
885db71995Sopenharmony_ciusing PFN_ACCESS = int (*)(const char* pathname, int mode);
895db71995Sopenharmony_ciusing PFN_FOPEN = FILE* (*)(const char* filename, const char* mode);
905db71995Sopenharmony_ciusing PFN_DLOPEN = void* (*)(const char* in_filename, int flags);
915db71995Sopenharmony_ciusing PFN_GETEUID = uid_t (*)(void);
925db71995Sopenharmony_ciusing PFN_GETEGID = gid_t (*)(void);
935db71995Sopenharmony_ci#if defined(HAVE_SECURE_GETENV) || defined(HAVE___SECURE_GETENV)
945db71995Sopenharmony_ciusing PFN_SEC_GETENV = char* (*)(const char* name);
955db71995Sopenharmony_ci#endif
965db71995Sopenharmony_ci
975db71995Sopenharmony_ci#if defined(__APPLE__)
985db71995Sopenharmony_ci#define real_opendir opendir
995db71995Sopenharmony_ci#define real_readdir readdir
1005db71995Sopenharmony_ci#define real_closedir closedir
1015db71995Sopenharmony_ci#define real_access access
1025db71995Sopenharmony_ci#define real_fopen fopen
1035db71995Sopenharmony_ci#define real_dlopen dlopen
1045db71995Sopenharmony_ci#define real_geteuid geteuid
1055db71995Sopenharmony_ci#define real_getegid getegid
1065db71995Sopenharmony_ci#if defined(HAVE_SECURE_GETENV)
1075db71995Sopenharmony_ci#define real_secure_getenv secure_getenv
1085db71995Sopenharmony_ci#endif
1095db71995Sopenharmony_ci#if defined(HAVE___SECURE_GETENV)
1105db71995Sopenharmony_ci#define real__secure_getenv __secure_getenv
1115db71995Sopenharmony_ci#endif
1125db71995Sopenharmony_ci#else
1135db71995Sopenharmony_ciPFN_OPENDIR real_opendir = nullptr;
1145db71995Sopenharmony_ciPFN_READDIR real_readdir = nullptr;
1155db71995Sopenharmony_ciPFN_CLOSEDIR real_closedir = nullptr;
1165db71995Sopenharmony_ciPFN_ACCESS real_access = nullptr;
1175db71995Sopenharmony_ciPFN_FOPEN real_fopen = nullptr;
1185db71995Sopenharmony_ciPFN_DLOPEN real_dlopen = nullptr;
1195db71995Sopenharmony_ciPFN_GETEUID real_geteuid = nullptr;
1205db71995Sopenharmony_ciPFN_GETEGID real_getegid = nullptr;
1215db71995Sopenharmony_ci#if defined(HAVE_SECURE_GETENV)
1225db71995Sopenharmony_ciPFN_SEC_GETENV real_secure_getenv = nullptr;
1235db71995Sopenharmony_ci#endif
1245db71995Sopenharmony_ci#if defined(HAVE___SECURE_GETENV)
1255db71995Sopenharmony_ciPFN_SEC_GETENV real__secure_getenv = nullptr;
1265db71995Sopenharmony_ci#endif
1275db71995Sopenharmony_ci#endif
1285db71995Sopenharmony_ci
1295db71995Sopenharmony_ciFRAMEWORK_EXPORT DIR* OPENDIR_FUNC_NAME(const char* path_name) {
1305db71995Sopenharmony_ci#if !defined(__APPLE__)
1315db71995Sopenharmony_ci    if (!real_opendir) real_opendir = (PFN_OPENDIR)dlsym(RTLD_NEXT, "opendir");
1325db71995Sopenharmony_ci#endif
1335db71995Sopenharmony_ci    if (platform_shim.is_during_destruction) {
1345db71995Sopenharmony_ci        return real_opendir(path_name);
1355db71995Sopenharmony_ci    }
1365db71995Sopenharmony_ci    DIR* dir;
1375db71995Sopenharmony_ci    if (platform_shim.is_fake_path(path_name)) {
1385db71995Sopenharmony_ci        auto real_path_name = platform_shim.get_real_path_from_fake_path(fs::path(path_name));
1395db71995Sopenharmony_ci        dir = real_opendir(real_path_name.c_str());
1405db71995Sopenharmony_ci        platform_shim.dir_entries.push_back(DirEntry{dir, std::string(path_name), {}, 0, true});
1415db71995Sopenharmony_ci    } else if (platform_shim.is_known_path(path_name)) {
1425db71995Sopenharmony_ci        dir = real_opendir(path_name);
1435db71995Sopenharmony_ci        platform_shim.dir_entries.push_back(DirEntry{dir, std::string(path_name), {}, 0, false});
1445db71995Sopenharmony_ci    } else {
1455db71995Sopenharmony_ci        dir = real_opendir(path_name);
1465db71995Sopenharmony_ci    }
1475db71995Sopenharmony_ci
1485db71995Sopenharmony_ci    return dir;
1495db71995Sopenharmony_ci}
1505db71995Sopenharmony_ci
1515db71995Sopenharmony_ciFRAMEWORK_EXPORT struct dirent* READDIR_FUNC_NAME(DIR* dir_stream) {
1525db71995Sopenharmony_ci#if !defined(__APPLE__)
1535db71995Sopenharmony_ci    if (!real_readdir) real_readdir = (PFN_READDIR)dlsym(RTLD_NEXT, "readdir");
1545db71995Sopenharmony_ci#endif
1555db71995Sopenharmony_ci    if (platform_shim.is_during_destruction) {
1565db71995Sopenharmony_ci        return real_readdir(dir_stream);
1575db71995Sopenharmony_ci    }
1585db71995Sopenharmony_ci    auto it = std::find_if(platform_shim.dir_entries.begin(), platform_shim.dir_entries.end(),
1595db71995Sopenharmony_ci                           [dir_stream](DirEntry const& entry) { return entry.directory == dir_stream; });
1605db71995Sopenharmony_ci
1615db71995Sopenharmony_ci    if (it == platform_shim.dir_entries.end()) {
1625db71995Sopenharmony_ci        return real_readdir(dir_stream);
1635db71995Sopenharmony_ci    }
1645db71995Sopenharmony_ci    // Folder was found but this is the first file to be read from it
1655db71995Sopenharmony_ci    if (it->current_index == 0) {
1665db71995Sopenharmony_ci        std::vector<struct dirent*> folder_contents;
1675db71995Sopenharmony_ci        std::vector<std::string> dirent_filenames;
1685db71995Sopenharmony_ci        while (true) {
1695db71995Sopenharmony_ci            struct dirent* dir_entry = real_readdir(dir_stream);
1705db71995Sopenharmony_ci            if (NULL == dir_entry) {
1715db71995Sopenharmony_ci                break;
1725db71995Sopenharmony_ci            }
1735db71995Sopenharmony_ci            folder_contents.push_back(dir_entry);
1745db71995Sopenharmony_ci            dirent_filenames.push_back(&dir_entry->d_name[0]);
1755db71995Sopenharmony_ci        }
1765db71995Sopenharmony_ci        auto real_path = it->folder_path;
1775db71995Sopenharmony_ci        if (it->is_fake_path) {
1785db71995Sopenharmony_ci            real_path = platform_shim.redirection_map.at(it->folder_path).str();
1795db71995Sopenharmony_ci        }
1805db71995Sopenharmony_ci        auto filenames = get_folder_contents(platform_shim.folders, real_path);
1815db71995Sopenharmony_ci
1825db71995Sopenharmony_ci        // Add the dirent structures in the order they appear in the FolderManager
1835db71995Sopenharmony_ci        // Ignore anything which wasn't in the FolderManager
1845db71995Sopenharmony_ci        for (auto const& file : filenames) {
1855db71995Sopenharmony_ci            for (size_t i = 0; i < dirent_filenames.size(); i++) {
1865db71995Sopenharmony_ci                if (file == dirent_filenames.at(i)) {
1875db71995Sopenharmony_ci                    it->contents.push_back(folder_contents.at(i));
1885db71995Sopenharmony_ci                    break;
1895db71995Sopenharmony_ci                }
1905db71995Sopenharmony_ci            }
1915db71995Sopenharmony_ci        }
1925db71995Sopenharmony_ci    }
1935db71995Sopenharmony_ci    if (it->current_index >= it->contents.size()) return nullptr;
1945db71995Sopenharmony_ci    return it->contents.at(it->current_index++);
1955db71995Sopenharmony_ci}
1965db71995Sopenharmony_ci
1975db71995Sopenharmony_ciFRAMEWORK_EXPORT int CLOSEDIR_FUNC_NAME(DIR* dir_stream) {
1985db71995Sopenharmony_ci#if !defined(__APPLE__)
1995db71995Sopenharmony_ci    if (!real_closedir) real_closedir = (PFN_CLOSEDIR)dlsym(RTLD_NEXT, "closedir");
2005db71995Sopenharmony_ci#endif
2015db71995Sopenharmony_ci    if (platform_shim.is_during_destruction) {
2025db71995Sopenharmony_ci        return real_closedir(dir_stream);
2035db71995Sopenharmony_ci    }
2045db71995Sopenharmony_ci    auto it = std::find_if(platform_shim.dir_entries.begin(), platform_shim.dir_entries.end(),
2055db71995Sopenharmony_ci                           [dir_stream](DirEntry const& entry) { return entry.directory == dir_stream; });
2065db71995Sopenharmony_ci
2075db71995Sopenharmony_ci    if (it != platform_shim.dir_entries.end()) {
2085db71995Sopenharmony_ci        platform_shim.dir_entries.erase(it);
2095db71995Sopenharmony_ci    }
2105db71995Sopenharmony_ci
2115db71995Sopenharmony_ci    return real_closedir(dir_stream);
2125db71995Sopenharmony_ci}
2135db71995Sopenharmony_ci
2145db71995Sopenharmony_ciFRAMEWORK_EXPORT int ACCESS_FUNC_NAME(const char* in_pathname, int mode) {
2155db71995Sopenharmony_ci#if !defined(__APPLE__)
2165db71995Sopenharmony_ci    if (!real_access) real_access = (PFN_ACCESS)dlsym(RTLD_NEXT, "access");
2175db71995Sopenharmony_ci#endif
2185db71995Sopenharmony_ci    fs::path path{in_pathname};
2195db71995Sopenharmony_ci    if (!path.has_parent_path()) {
2205db71995Sopenharmony_ci        return real_access(in_pathname, mode);
2215db71995Sopenharmony_ci    }
2225db71995Sopenharmony_ci
2235db71995Sopenharmony_ci    if (platform_shim.is_fake_path(path.parent_path())) {
2245db71995Sopenharmony_ci        fs::path real_path = platform_shim.get_real_path_from_fake_path(path.parent_path());
2255db71995Sopenharmony_ci        real_path /= path.filename();
2265db71995Sopenharmony_ci        return real_access(real_path.c_str(), mode);
2275db71995Sopenharmony_ci    }
2285db71995Sopenharmony_ci    return real_access(in_pathname, mode);
2295db71995Sopenharmony_ci}
2305db71995Sopenharmony_ci
2315db71995Sopenharmony_ciFRAMEWORK_EXPORT FILE* FOPEN_FUNC_NAME(const char* in_filename, const char* mode) {
2325db71995Sopenharmony_ci#if !defined(__APPLE__)
2335db71995Sopenharmony_ci    if (!real_fopen) real_fopen = (PFN_FOPEN)dlsym(RTLD_NEXT, "fopen");
2345db71995Sopenharmony_ci#endif
2355db71995Sopenharmony_ci    fs::path path{in_filename};
2365db71995Sopenharmony_ci    if (!path.has_parent_path()) {
2375db71995Sopenharmony_ci        return real_fopen(in_filename, mode);
2385db71995Sopenharmony_ci    }
2395db71995Sopenharmony_ci
2405db71995Sopenharmony_ci    FILE* f_ptr;
2415db71995Sopenharmony_ci    if (platform_shim.is_fake_path(path.parent_path())) {
2425db71995Sopenharmony_ci        auto real_path = platform_shim.get_real_path_from_fake_path(path.parent_path()) / path.filename();
2435db71995Sopenharmony_ci        f_ptr = real_fopen(real_path.c_str(), mode);
2445db71995Sopenharmony_ci    } else {
2455db71995Sopenharmony_ci        f_ptr = real_fopen(in_filename, mode);
2465db71995Sopenharmony_ci    }
2475db71995Sopenharmony_ci
2485db71995Sopenharmony_ci    return f_ptr;
2495db71995Sopenharmony_ci}
2505db71995Sopenharmony_ci
2515db71995Sopenharmony_ciFRAMEWORK_EXPORT void* DLOPEN_FUNC_NAME(const char* in_filename, int flags) {
2525db71995Sopenharmony_ci#if !defined(__APPLE__)
2535db71995Sopenharmony_ci    if (!real_dlopen) real_dlopen = (PFN_DLOPEN)dlsym(RTLD_NEXT, "dlopen");
2545db71995Sopenharmony_ci#endif
2555db71995Sopenharmony_ci
2565db71995Sopenharmony_ci    if (platform_shim.is_dlopen_redirect_name(in_filename)) {
2575db71995Sopenharmony_ci        return real_dlopen(platform_shim.dlopen_redirection_map[in_filename].c_str(), flags);
2585db71995Sopenharmony_ci    }
2595db71995Sopenharmony_ci    return real_dlopen(in_filename, flags);
2605db71995Sopenharmony_ci}
2615db71995Sopenharmony_ci
2625db71995Sopenharmony_ciFRAMEWORK_EXPORT uid_t GETEUID_FUNC_NAME(void) {
2635db71995Sopenharmony_ci#if !defined(__APPLE__)
2645db71995Sopenharmony_ci    if (!real_geteuid) real_geteuid = (PFN_GETEUID)dlsym(RTLD_NEXT, "geteuid");
2655db71995Sopenharmony_ci#endif
2665db71995Sopenharmony_ci    if (platform_shim.use_fake_elevation) {
2675db71995Sopenharmony_ci        // Root on linux is 0, so force pretending like we're root
2685db71995Sopenharmony_ci        return 0;
2695db71995Sopenharmony_ci    } else {
2705db71995Sopenharmony_ci        return real_geteuid();
2715db71995Sopenharmony_ci    }
2725db71995Sopenharmony_ci}
2735db71995Sopenharmony_ci
2745db71995Sopenharmony_ciFRAMEWORK_EXPORT gid_t GETEGID_FUNC_NAME(void) {
2755db71995Sopenharmony_ci#if !defined(__APPLE__)
2765db71995Sopenharmony_ci    if (!real_getegid) real_getegid = (PFN_GETEGID)dlsym(RTLD_NEXT, "getegid");
2775db71995Sopenharmony_ci#endif
2785db71995Sopenharmony_ci    if (platform_shim.use_fake_elevation) {
2795db71995Sopenharmony_ci        // Root on linux is 0, so force pretending like we're root
2805db71995Sopenharmony_ci        return 0;
2815db71995Sopenharmony_ci    } else {
2825db71995Sopenharmony_ci        return real_getegid();
2835db71995Sopenharmony_ci    }
2845db71995Sopenharmony_ci}
2855db71995Sopenharmony_ci
2865db71995Sopenharmony_ci#if !defined(TARGET_OS_IPHONE)
2875db71995Sopenharmony_ci#if defined(HAVE_SECURE_GETENV)
2885db71995Sopenharmony_ciFRAMEWORK_EXPORT char* SECURE_GETENV_FUNC_NAME(const char* name) {
2895db71995Sopenharmony_ci#if !defined(__APPLE__)
2905db71995Sopenharmony_ci    if (!real_secure_getenv) real_secure_getenv = (PFN_SEC_GETENV)dlsym(RTLD_NEXT, "secure_getenv");
2915db71995Sopenharmony_ci#endif
2925db71995Sopenharmony_ci    if (platform_shim.use_fake_elevation) {
2935db71995Sopenharmony_ci        return NULL;
2945db71995Sopenharmony_ci    } else {
2955db71995Sopenharmony_ci        return real_secure_getenv(name);
2965db71995Sopenharmony_ci    }
2975db71995Sopenharmony_ci}
2985db71995Sopenharmony_ci#endif
2995db71995Sopenharmony_ci#if defined(HAVE___SECURE_GETENV)
3005db71995Sopenharmony_ciFRAMEWORK_EXPORT char* __SECURE_GETENV_FUNC_NAME(const char* name) {
3015db71995Sopenharmony_ci#if !defined(__APPLE__)
3025db71995Sopenharmony_ci    if (!real__secure_getenv) real__secure_getenv = (PFN_SEC_GETENV)dlsym(RTLD_NEXT, "__secure_getenv");
3035db71995Sopenharmony_ci#endif
3045db71995Sopenharmony_ci
3055db71995Sopenharmony_ci    if (platform_shim.use_fake_elevation) {
3065db71995Sopenharmony_ci        return NULL;
3075db71995Sopenharmony_ci    } else {
3085db71995Sopenharmony_ci        return real__secure_getenv(name);
3095db71995Sopenharmony_ci    }
3105db71995Sopenharmony_ci}
3115db71995Sopenharmony_ci#endif
3125db71995Sopenharmony_ci#endif
3135db71995Sopenharmony_ci#if defined(__APPLE__)
3145db71995Sopenharmony_ciFRAMEWORK_EXPORT CFBundleRef my_CFBundleGetMainBundle() {
3155db71995Sopenharmony_ci    static CFBundleRef global_bundle{};
3165db71995Sopenharmony_ci    return reinterpret_cast<CFBundleRef>(&global_bundle);
3175db71995Sopenharmony_ci}
3185db71995Sopenharmony_ciFRAMEWORK_EXPORT CFURLRef my_CFBundleCopyResourcesDirectoryURL([[maybe_unused]] CFBundleRef bundle) {
3195db71995Sopenharmony_ci    static CFURLRef global_url{};
3205db71995Sopenharmony_ci    return reinterpret_cast<CFURLRef>(&global_url);
3215db71995Sopenharmony_ci}
3225db71995Sopenharmony_ciFRAMEWORK_EXPORT Boolean my_CFURLGetFileSystemRepresentation([[maybe_unused]] CFURLRef url,
3235db71995Sopenharmony_ci                                                             [[maybe_unused]] Boolean resolveAgainstBase, UInt8* buffer,
3245db71995Sopenharmony_ci                                                             CFIndex maxBufLen) {
3255db71995Sopenharmony_ci    if (!platform_shim.bundle_contents.empty()) {
3265db71995Sopenharmony_ci        CFIndex copy_len = (CFIndex)platform_shim.bundle_contents.size();
3275db71995Sopenharmony_ci        if (copy_len > maxBufLen) {
3285db71995Sopenharmony_ci            copy_len = maxBufLen;
3295db71995Sopenharmony_ci        }
3305db71995Sopenharmony_ci        strncpy(reinterpret_cast<char*>(buffer), platform_shim.bundle_contents.c_str(), copy_len);
3315db71995Sopenharmony_ci        return TRUE;
3325db71995Sopenharmony_ci    }
3335db71995Sopenharmony_ci    return FALSE;
3345db71995Sopenharmony_ci}
3355db71995Sopenharmony_ci#endif
3365db71995Sopenharmony_ci
3375db71995Sopenharmony_ci/* Shiming functions on apple is limited by the linker prefering to not use functions in the
3385db71995Sopenharmony_ci * executable in loaded dylibs. By adding an interposer, we redirect the linker to use our
3395db71995Sopenharmony_ci * version of the function over the real one, thus shimming the system function.
3405db71995Sopenharmony_ci */
3415db71995Sopenharmony_ci#if defined(__APPLE__)
3425db71995Sopenharmony_ci#define MACOS_ATTRIB __attribute__((section("__DATA,__interpose")))
3435db71995Sopenharmony_ci#define VOIDP_CAST(_func) reinterpret_cast<const void*>(&_func)
3445db71995Sopenharmony_ci
3455db71995Sopenharmony_cistruct Interposer {
3465db71995Sopenharmony_ci    const void* shim_function;
3475db71995Sopenharmony_ci    const void* underlying_function;
3485db71995Sopenharmony_ci};
3495db71995Sopenharmony_ci
3505db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_opendir MACOS_ATTRIB = {VOIDP_CAST(my_opendir), VOIDP_CAST(opendir)};
3515db71995Sopenharmony_ci// don't intercept readdir as it crashes when using ASAN with macOS
3525db71995Sopenharmony_ci// __attribute__((used)) static Interposer _interpose_readdir MACOS_ATTRIB = {VOIDP_CAST(my_readdir), VOIDP_CAST(readdir)};
3535db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_closedir MACOS_ATTRIB = {VOIDP_CAST(my_closedir), VOIDP_CAST(closedir)};
3545db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_access MACOS_ATTRIB = {VOIDP_CAST(my_access), VOIDP_CAST(access)};
3555db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_fopen MACOS_ATTRIB = {VOIDP_CAST(my_fopen), VOIDP_CAST(fopen)};
3565db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_dlopen MACOS_ATTRIB = {VOIDP_CAST(my_dlopen), VOIDP_CAST(dlopen)};
3575db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_euid MACOS_ATTRIB = {VOIDP_CAST(my_geteuid), VOIDP_CAST(geteuid)};
3585db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_egid MACOS_ATTRIB = {VOIDP_CAST(my_getegid), VOIDP_CAST(getegid)};
3595db71995Sopenharmony_ci#if !defined(TARGET_OS_IPHONE)
3605db71995Sopenharmony_ci#if defined(HAVE_SECURE_GETENV)
3615db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_secure_getenv MACOS_ATTRIB = {VOIDP_CAST(my_secure_getenv),
3625db71995Sopenharmony_ci                                                                                 VOIDP_CAST(secure_getenv)};
3635db71995Sopenharmony_ci#endif
3645db71995Sopenharmony_ci#if defined(HAVE___SECURE_GETENV)
3655db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose__secure_getenv MACOS_ATTRIB = {VOIDP_CAST(my__secure_getenv),
3665db71995Sopenharmony_ci                                                                                  VOIDP_CAST(__secure_getenv)};
3675db71995Sopenharmony_ci#endif
3685db71995Sopenharmony_ci#endif
3695db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_CFBundleGetMainBundle MACOS_ATTRIB = {VOIDP_CAST(my_CFBundleGetMainBundle),
3705db71995Sopenharmony_ci                                                                                         VOIDP_CAST(CFBundleGetMainBundle)};
3715db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_CFBundleCopyResourcesDirectoryURL MACOS_ATTRIB = {
3725db71995Sopenharmony_ci    VOIDP_CAST(my_CFBundleCopyResourcesDirectoryURL), VOIDP_CAST(CFBundleCopyResourcesDirectoryURL)};
3735db71995Sopenharmony_ci__attribute__((used)) static Interposer _interpose_CFURLGetFileSystemRepresentation MACOS_ATTRIB = {
3745db71995Sopenharmony_ci    VOIDP_CAST(my_CFURLGetFileSystemRepresentation), VOIDP_CAST(CFURLGetFileSystemRepresentation)};
3755db71995Sopenharmony_ci
3765db71995Sopenharmony_ci#endif
3775db71995Sopenharmony_ci}  // extern "C"
378