#ifdef __HAIKU__ // clang-format off #include // For BAppFileInfo and version_info #include // B_OK, strerror, status_t #include // For BFile #include // get_system_info, system_info #include // PATH_MAX #include // std::strlen #include // DBUS_TYPE_* #include // DBUS_BUS_SESSION #include // BPackageKit::BPackageInfoSet #include // BPackageKit::BPackageInfo #include // BPackageKit::BPackageRoster #include // ucred, getsockopt, SOL_SOCKET, SO_PEERCRED #include // statvfs #include // std::move #include "src/core/package.hpp" #include "src/util/defs.hpp" #include "src/util/error.hpp" #include "src/util/helpers.hpp" #include "src/util/logging.hpp" #include "src/util/types.hpp" #include "os.hpp" // clang-format on using namespace util::types; using util::error::DracError, util::error::DracErrorCode; using util::helpers::GetEnv; namespace os { fn GetOSVersion() -> Result { BFile file; status_t status = file.SetTo("/boot/system/lib/libbe.so", B_READ_ONLY); if (status != B_OK) return Err(DracError(DracErrorCode::InternalError, "Error opening /boot/system/lib/libbe.so")); BAppFileInfo appInfo; status = appInfo.SetTo(&file); if (status != B_OK) return Err(DracError(DracErrorCode::InternalError, "Error initializing BAppFileInfo")); version_info versionInfo; status = appInfo.GetVersionInfo(&versionInfo, B_APP_VERSION_KIND); if (status != B_OK) return Err(DracError(DracErrorCode::InternalError, "Error reading version info attribute")); String versionShortString = versionInfo.short_info; if (versionShortString.empty()) return Err(DracError(DracErrorCode::InternalError, "Version info short_info is empty")); return std::format("Haiku {}", versionShortString); } fn GetMemInfo() -> Result { system_info sysinfo; const status_t status = get_system_info(&sysinfo); if (status != B_OK) return Err(DracError(DracErrorCode::InternalError, std::format("get_system_info failed: {}", strerror(status)))); return static_cast(sysinfo.max_pages) * B_PAGE_SIZE; } fn GetNowPlaying() -> Result { return Err(DracError(DracErrorCode::NotSupported, "Now playing is not supported on Haiku")); } fn GetWindowManager() -> Result { return "app_server"; } fn GetDesktopEnvironment() -> Result { return "Haiku Desktop Environment"; } fn GetShell() -> Result { if (const Result shellPath = GetEnv("SHELL")) { // clang-format off constexpr Array, 5> shellMap {{ { "bash", "Bash" }, { "zsh", "Zsh" }, { "fish", "Fish" }, { "nu", "Nushell" }, { "sh", "SH" }, // sh last because other shells contain "sh" }}; // clang-format on for (const auto& [exe, name] : shellMap) if (shellPath->contains(exe)) return String(name); return *shellPath; // fallback to the raw shell path } return Err(DracError(DracErrorCode::NotFound, "Could not find SHELL environment variable")); } fn GetHost() -> Result { Array hostnameBuffer {}; if (gethostname(hostnameBuffer.data(), hostnameBuffer.size()) != 0) return Err(DracError( DracErrorCode::ApiUnavailable, std::format("gethostname() failed: {} (errno {})", strerror(errno), errno) )); hostnameBuffer.at(HOST_NAME_MAX) = '\0'; return String(hostnameBuffer.data(), hostnameBuffer.size()); } fn GetKernelVersion() -> Result { system_info sysinfo; const status_t status = get_system_info(&sysinfo); if (status != B_OK) return Err(DracError(DracErrorCode::InternalError, std::format("get_system_info failed: {}", strerror(status)))); return std::to_string(sysinfo.kernel_version); } fn GetDiskUsage() -> Result { struct statvfs stat; if (statvfs("/boot", &stat) == -1) return Err(DracError::withErrno(std::format("Failed to get filesystem stats for '/boot' (statvfs call failed)"))); return DiskSpace { .used_bytes = (stat.f_blocks * stat.f_frsize) - (stat.f_bfree * stat.f_frsize), .total_bytes = stat.f_blocks * stat.f_frsize, }; } } // namespace os namespace package { fn GetHaikuCount() -> Result { BPackageKit::BPackageRoster roster; BPackageKit::BPackageInfoSet packageList; const status_t status = roster.GetActivePackages(BPackageKit::B_PACKAGE_INSTALLATION_LOCATION_SYSTEM, packageList); if (status != B_OK) return Err(DracError(DracErrorCode::ApiUnavailable, "Failed to get active package list")); return static_cast(packageList.CountInfos()); } } // namespace package #endif // __HAIKU__