/* * Copyright (c) Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include namespace ams::fs { namespace { constinit bool g_auto_abort_enabled = true; /* NOTE: This generates a global constructor. */ os::SdkThreadLocalStorage g_context_tls; } void SetEnabledAutoAbort(bool enabled) { g_auto_abort_enabled = enabled; } AbortSpecifier DefaultResultHandler(Result result) { AMS_UNUSED(result); if (g_auto_abort_enabled) { return AbortSpecifier::Default; } else { return AbortSpecifier::Return; } } AbortSpecifier AlwaysReturnResultHandler(Result result) { AMS_UNUSED(result); return AbortSpecifier::Return; } constinit FsContext g_default_context(DefaultResultHandler); constinit FsContext g_always_return_context(AlwaysReturnResultHandler); void SetDefaultFsContextResultHandler(const ResultHandler handler) { if (handler == nullptr) { g_default_context.SetHandler(DefaultResultHandler); } else { g_default_context.SetHandler(handler); } } const FsContext *GetCurrentThreadFsContext() { const FsContext *context = reinterpret_cast(g_context_tls.GetValue()); if (context == nullptr) { context = std::addressof(g_default_context); } return context; } void SetCurrentThreadFsContext(const FsContext *context) { g_context_tls.SetValue(reinterpret_cast(context)); } ScopedAutoAbortDisabler::ScopedAutoAbortDisabler() : m_prev_context(GetCurrentThreadFsContext()) { SetCurrentThreadFsContext(std::addressof(g_always_return_context)); } }