| 1691 | } |
| 1692 | |
| 1693 | bool FileSystem::IsWritable(StringView path) |
| 1694 | { |
| 1695 | if (path.empty()) return false; |
| 1696 | |
| 1697 | #if defined(DEATH_TARGET_WINDOWS_RT) |
| 1698 | SmallVector<wchar_t, MAX_PATH + 1> pathW(DefaultInit, path.size() + 1); |
| 1699 | Utf8::ToUtf16(pathW.data(), std::int32_t(pathW.size()), path.data(), std::int32_t(path.size())); |
| 1700 | WIN32_FILE_ATTRIBUTE_DATA lpFileInfo; |
| 1701 | return (::GetFileAttributesExFromAppW(pathW.data(), GetFileExInfoStandard, &lpFileInfo) && (lpFileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0); |
| 1702 | #elif defined(DEATH_TARGET_WINDOWS) |
| 1703 | SmallVector<wchar_t, MAX_PATH + 1> pathW(DefaultInit, path.size() + 1); |
| 1704 | Utf8::ToUtf16(pathW.data(), std::int32_t(pathW.size()), path.data(), std::int32_t(path.size())); |
| 1705 | const DWORD attrs = ::GetFileAttributesW(pathW.data()); |
| 1706 | return (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_READONLY) == 0); |
| 1707 | #else |
| 1708 | auto nullTerminatedPath = String::nullTerminatedView(path); |
| 1709 | # if defined(DEATH_TARGET_ANDROID) |
| 1710 | if (AndroidAssetStream::TryGetAssetPath(nullTerminatedPath)) { |
| 1711 | // Android assets are not writable |
| 1712 | return false; |
| 1713 | } |
| 1714 | # endif |
| 1715 | struct stat sb; |
| 1716 | if (::stat(nullTerminatedPath.data(), &sb) == 0) { |
| 1717 | return ((sb.st_mode & S_IWUSR) != 0); |
| 1718 | } |
| 1719 | return false; |
| 1720 | #endif |
| 1721 | } |
| 1722 | |
| 1723 | bool FileSystem::IsExecutable(StringView path) |
| 1724 | { |