diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 4c8d98ce2f6..2101b9b5e83 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -86,7 +86,7 @@ jobs:
variants: ${{ matrix.configuration }}
steps:
- name: Checkout code
- uses: actions/checkout@v5
+ uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
@@ -95,14 +95,14 @@ jobs:
with:
python-version: "3.11"
- name: Checkout build variables
- uses: actions/checkout@v5
+ uses: actions/checkout@v6
with:
repository: secondlife/build-variables
ref: master
path: .build-variables
- name: Checkout master-message-template
- uses: actions/checkout@v5
+ uses: actions/checkout@v6
with:
repository: secondlife/master-message-template
path: .master-message-template
@@ -112,7 +112,7 @@ jobs:
- name: Cache autobuild packages
id: cache-installables
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: .autobuild-installables
key: ${{ runner.os }}-64-${{ matrix.configuration }}-${{ hashFiles('autobuild.xml') }}
@@ -265,7 +265,7 @@ jobs:
- name: Upload executable
if: steps.build.outputs.viewer_app
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v6
with:
name: "${{ steps.build.outputs.artifact }}-app"
path: |
@@ -275,13 +275,13 @@ jobs:
# artifact for that too.
- name: Upload symbol file
if: steps.build.outputs.symbolfile
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v6
with:
name: "${{ steps.build.outputs.artifact }}-symbols"
path: ${{ steps.build.outputs.symbolfile }}
- name: Upload metadata
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v6
with:
name: "${{ steps.build.outputs.artifact }}-metadata"
# emitted by build.sh, possibly multiple lines
@@ -289,7 +289,7 @@ jobs:
${{ steps.build.outputs.metadata }}
- name: Upload physics package
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v6
# should only be set for viewer-private
if: matrix.configuration == 'Release' && steps.build.outputs.physicstpv
with:
@@ -370,13 +370,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download viewer exe
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v7
with:
name: Windows-app
path: _artifacts
- name: Download Windows Symbols
if: env.BUGSPLAT_DATABASE && env.SYMBOL_UPLOAD_CLIENT_ID
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v7
with:
name: Windows-symbols
- name: Extract viewer pdb
@@ -409,7 +409,7 @@ jobs:
steps:
- name: Download Mac Symbols
if: env.BUGSPLAT_DATABASE && env.SYMBOL_UPLOAD_CLIENT_ID
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v7
with:
name: macOS-symbols
- name: Post Mac symbols
@@ -431,11 +431,11 @@ jobs:
runs-on: ubuntu-latest
if: needs.setup.outputs.release_run
steps:
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v7
with:
pattern: "*-installer"
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v7
with:
pattern: "*-metadata"
diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml
index 8f942fa11bc..93bcafdea85 100644
--- a/.github/workflows/pre-commit.yaml
+++ b/.github/workflows/pre-commit.yaml
@@ -11,7 +11,7 @@ jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v5
+ - uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: 3.x
diff --git a/autobuild.xml b/autobuild.xml
index d58a785b6b6..89b951c10c4 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -106,11 +106,11 @@
archive
name
darwin64
@@ -120,11 +120,11 @@
archive
name
linux64
@@ -134,11 +134,11 @@
archive
name
windows64
@@ -151,7 +151,7 @@
copyright
(see individual source files)
version
- 1.86
+ 1.90.0-c7a9feb
name
boost
description
@@ -212,11 +212,11 @@
archive
name
darwin64
@@ -226,11 +226,11 @@
archive
name
linux64
@@ -240,11 +240,11 @@
archive
name
windows64
@@ -257,7 +257,7 @@
copyright
Copyright 2006 Sony Computer Entertainment Inc.
version
- 2.3.0-r10
+ 2.3.0-r11
name
colladadom
@@ -328,11 +328,11 @@
archive
name
darwin64
@@ -342,11 +342,11 @@
archive
name
linux64
@@ -356,11 +356,11 @@
archive
name
windows64
@@ -373,7 +373,7 @@
copyright
Copyright (c) 1996 - 2014, Daniel Stenberg, (daniel@haxx.se).
version
- 7.54.1-13259824618
+ 7.54.1-20982000504
name
curl
description
@@ -634,11 +634,11 @@
archive
name
darwin64
@@ -648,11 +648,11 @@
archive
name
linux64
@@ -662,11 +662,11 @@
archive
name
windows64
@@ -679,7 +679,7 @@
copyright
Copyright 2006, 2007, 2008, 2009, 2010 by David Turner, Robert Wilhelm, and Werner Lemberg.
version
- 2.13.3-r3
+ 2.13.3-r4
name
freetype
description
@@ -1226,11 +1226,11 @@
archive
name
darwin64
@@ -1240,11 +1240,11 @@
archive
name
linux64
@@ -1254,11 +1254,11 @@
archive
name
windows64
@@ -1271,7 +1271,7 @@
copyright
Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson
version
- 1.6.44-r2
+ 1.6.53-eea12b7
name
libpng
description
@@ -1316,11 +1316,11 @@
archive
name
darwin64
@@ -1330,11 +1330,11 @@
archive
name
linux64
@@ -1344,11 +1344,11 @@
archive
name
windows64
@@ -1361,7 +1361,7 @@
copyright
Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.
version
- 2.13.5-r2
+ 2.13.9-d53cd6f
name
libxml2
description
@@ -1547,11 +1547,11 @@
archive
name
darwin64
@@ -1561,11 +1561,11 @@
archive
name
linux64
@@ -1575,11 +1575,11 @@
archive
name
windows64
@@ -1671,11 +1671,11 @@
archive
name
darwin64
@@ -1685,11 +1685,11 @@
archive
name
linux64
@@ -1699,11 +1699,11 @@
archive
name
windows64
@@ -1716,7 +1716,7 @@
copyright
This project uses the zlib license. Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
version
- 4.0.7-r3
+ 4.0.7-r4
name
minizip-ng
canonical_repo
@@ -2079,11 +2079,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
name
darwin64
@@ -2093,11 +2093,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
name
linux64
@@ -2107,11 +2107,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
name
windows64
@@ -2124,7 +2124,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
copyright
Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved; Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
version
- 1.1.1w-r3
+ 1.1.1w-r4
name
openssl
description
@@ -2731,11 +2731,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
name
darwin64
@@ -2745,11 +2745,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
name
linux64
@@ -2759,11 +2759,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
name
windows64
@@ -2776,7 +2776,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
copyright
Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
version
- 2.2.3-dev0.g8aa13e3.d20250206
+ 2.2.5-0d88d03
name
zlib-ng
canonical_repo
diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake
index b57c33c3e00..3bea85f3eaa 100644
--- a/indra/cmake/Boost.cmake
+++ b/indra/cmake/Boost.cmake
@@ -20,48 +20,42 @@ if (WINDOWS)
find_library(BOOST_CONTEXT_LIBRARY
NAMES
+ libboost_context
libboost_context-mt
libboost_context-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_FIBER_LIBRARY
NAMES
+ libboost_fiber
libboost_fiber-mt
libboost_fiber-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_FILESYSTEM_LIBRARY
NAMES
+ libboost_filesystem
libboost_filesystem-mt
libboost_filesystem-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_PROGRAMOPTIONS_LIBRARY
NAMES
+ libboost_program_options
libboost_program_options-mt
libboost_program_options-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
- find_library(BOOST_REGEX_LIBRARY
- NAMES
- libboost_regex-mt
- libboost_regex-mt${addrsfx}
- PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-
- find_library(BOOST_SYSTEM_LIBRARY
- NAMES
- libboost_system-mt
- libboost_system-mt${addrsfx}
- PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-
find_library(BOOST_THREAD_LIBRARY
NAMES
+ libboost_thread
libboost_thread-mt
libboost_thread-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_URL_LIBRARY
NAMES
+ libboost_url
libboost_url-mt
libboost_url-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
@@ -70,48 +64,42 @@ else (WINDOWS)
find_library(BOOST_CONTEXT_LIBRARY
NAMES
+ boost_context
boost_context-mt
boost_context-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_FIBER_LIBRARY
NAMES
+ boost_fiber
boost_fiber-mt
boost_fiber-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_FILESYSTEM_LIBRARY
NAMES
+ boost_filesystem
boost_filesystem-mt
boost_filesystem-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_PROGRAMOPTIONS_LIBRARY
NAMES
+ boost_program_options
boost_program_options-mt
boost_program_options-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
- find_library(BOOST_REGEX_LIBRARY
- NAMES
- boost_regex-mt
- boost_regex-mt${addrsfx}
- PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-
- find_library(BOOST_SYSTEM_LIBRARY
- NAMES
- boost_system-mt
- boost_system-mt${addrsfx}
- PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-
find_library(BOOST_THREAD_LIBRARY
NAMES
+ boost_thread
boost_thread-mt
boost_thread-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
find_library(BOOST_URL_LIBRARY
NAMES
+ boost_url
boost_url-mt
boost_url-mt${addrsfx}
PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
@@ -123,8 +111,6 @@ target_link_libraries(ll::boost INTERFACE
${BOOST_CONTEXT_LIBRARY}
${BOOST_FILESYSTEM_LIBRARY}
${BOOST_PROGRAMOPTIONS_LIBRARY}
- ${BOOST_REGEX_LIBRARY}
- ${BOOST_SYSTEM_LIBRARY}
${BOOST_THREAD_LIBRARY}
${BOOST_URL_LIBRARY})
diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake
index 7cce190f6a5..428f9e33267 100644
--- a/indra/cmake/Python.cmake
+++ b/indra/cmake/Python.cmake
@@ -1,57 +1,18 @@
-# -*- cmake -*-
-
-set(PYTHONINTERP_FOUND)
-
-if (DEFINED ENV{PYTHON})
- # Allow python executable to be explicitly set
- set(python "$ENV{PYTHON}")
- set(PYTHONINTERP_FOUND ON)
-elseif (WINDOWS)
- # On Windows, explicitly avoid Cygwin Python.
-
- # if the user has their own version of Python installed, prefer that
- foreach(hive HKEY_CURRENT_USER HKEY_LOCAL_MACHINE)
- # prefer more recent Python versions to older ones, if multiple versions
- # are installed
- foreach(pyver 3.13 3.12 3.11 3.10 3.9 3.8 3.7)
- list(APPEND regpaths "[${hive}\\SOFTWARE\\Python\\PythonCore\\${pyver}\\InstallPath]")
- endforeach()
- endforeach()
-
- # TODO: This logic has the disadvantage that if you have multiple versions
- # of Python installed, the selected path won't necessarily be the newest -
- # e.g. this GLOB will prefer Python310 to Python311. But since pymaybe is
- # checked AFTER the registry entries, this will only surface as a problem if
- # no installed Python appears in the registry.
- file(GLOB pymaybe
- "$ENV{PROGRAMFILES}/Python*"
-## "$ENV{PROGRAMFILES(X86)}/Python*"
- # The Windows environment variable is in fact as shown above, but CMake
- # disallows querying an environment variable containing parentheses -
- # thanks, Windows. Fudge by just appending " (x86)" to $PROGRAMFILES and
- # hoping for the best.
- "$ENV{PROGRAMFILES} (x86)/Python*"
- "c:/Python*")
-
- find_program(python
- NAMES python3.exe python.exe
- NO_DEFAULT_PATH # added so that cmake does not find cygwin python
- PATHS
- ${regpaths}
- ${pymaybe}
- )
- find_package(Python3 COMPONENTS Interpreter)
-else()
- find_program(python python3)
-
- if (python)
- set(PYTHONINTERP_FOUND ON)
- endif (python)
-endif (DEFINED ENV{PYTHON})
-
-if (NOT python)
- message(FATAL_ERROR "No Python interpreter found")
-endif (NOT python)
-
-set(PYTHON_EXECUTABLE "${python}" CACHE FILEPATH "Python interpreter for builds")
+# Allow explicit Python path via environment variable
+if(DEFINED ENV{PYTHON})
+ set(Python3_ROOT_DIR "$ENV{PYTHON}")
+endif()
+
+# On Windows, prefer registry entries to avoid Cygwin/MSYS Python
+# The registry is searched first by default, which finds native Windows Python
+# installations rather than Cygwin/MSYS Python
+if(WINDOWS)
+ set(Python3_FIND_REGISTRY FIRST CACHE STRING "Python search order")
+endif()
+
+# Find Python 3 interpreter
+find_package(Python3 REQUIRED COMPONENTS Interpreter)
+
+# Set legacy variable name for compatibility with existing code
+set(PYTHON_EXECUTABLE "${Python3_EXECUTABLE}" CACHE FILEPATH "Python interpreter for builds")
mark_as_advanced(PYTHON_EXECUTABLE)
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index 613c4081571..6f2f7eae61d 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -225,6 +225,7 @@ void LLAudioEngine::updateChannels()
void LLAudioEngine::idle()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA;
// "Update" all of our audio sources, clean up dead ones.
// Primarily does position updating, cleanup of unused audio sources.
// Also does regeneration of the current priority of each audio source.
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 2de9deea701..32226a62e6c 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -68,6 +68,7 @@ set(llcommon_SOURCE_FILES
llmetricperformancetester.cpp
llmortician.cpp
llmutex.cpp
+ llpointer.cpp
llptrto.cpp
llpredicate.cpp
llprocess.cpp
@@ -101,6 +102,7 @@ set(llcommon_SOURCE_FILES
lluri.cpp
lluriparser.cpp
lluuid.cpp
+ llwatchdog.cpp
llworkerthread.cpp
hbxxh.cpp
u64.cpp
@@ -240,6 +242,7 @@ set(llcommon_HEADER_FILES
lluri.h
lluriparser.h
lluuid.h
+ llwatchdog.h
llwin32headers.h
llworkerthread.h
hbxxh.h
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index c532620daa1..f92bb98ba6b 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -93,6 +93,7 @@ bool LLApp::sDisableCrashlogger = false;
LLScalarCond LLApp::sStatus{LLApp::APP_STATUS_STOPPED};
LLAppErrorHandler LLApp::sErrorHandler = NULL;
+bool gDisconnected = false;
LLApp::LLApp()
{
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index 57f5a112d9b..ce09c566a9d 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -50,6 +50,8 @@ void clear_signals();
#endif
+extern bool gDisconnected;
+
class LL_COMMON_API LLApp
{
public:
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 5205699b92c..5545bb71af4 100644
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -41,6 +41,9 @@
#include "llstring.h"
#include "llfasttimer.h"
+#include
+#include
+
static const F64 LL_APR_USEC_PER_SEC = 1000000.0;
// should be APR_USEC_PER_SEC, but that relies on INT64_C which
// isn't defined in glib under our build set up for some reason
@@ -64,7 +67,7 @@ std::string LLDate::asString() const
{
std::ostringstream stream;
toStream(stream);
- return stream.str();
+ return std::move(stream).str();
}
//@ brief Converts time in seconds since EPOCH
@@ -184,7 +187,7 @@ bool LLDate::split(S32 *year, S32 *month, S32 *day, S32 *hour, S32 *min, S32 *se
bool LLDate::fromString(const std::string& iso8601_date)
{
- std::istringstream stream(iso8601_date);
+ boost::iostreams::stream stream(iso8601_date.data(), iso8601_date.size());
return fromStream(stream);
}
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index b14464382b7..6f5e57c3de1 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -480,7 +480,7 @@ namespace
}
- typedef std::map LevelMap;
+ typedef std::unordered_map LevelMap;
typedef std::vector Recorders;
typedef std::vector CallSiteVector;
@@ -501,7 +501,7 @@ namespace
LevelMap mClassLevelMap;
LevelMap mFileLevelMap;
LevelMap mTagLevelMap;
- std::map mUniqueLogMessages;
+ std::unordered_map mUniqueLogMessages;
LLError::FatalFunction mCrashFunction;
LLError::TimeFunction mTimeFunction;
@@ -1404,7 +1404,7 @@ namespace LLError
{
std::ostringstream message_stream;
- std::map::iterator messageIter = s->mUniqueLogMessages.find(message);
+ auto messageIter = s->mUniqueLogMessages.find(message);
if (messageIter != s->mUniqueLogMessages.end())
{
messageIter->second++;
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index d254fa54074..3c58d1df227 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -70,7 +70,6 @@ namespace LLError
Setting a level means log messages at that level or above.
*/
- LL_COMMON_API void setPrintLocation(bool);
LL_COMMON_API void setDefaultLevel(LLError::ELevel);
LL_COMMON_API ELevel getDefaultLevel();
LL_COMMON_API void setAlwaysFlush(bool flush);
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index e1fc4764f66..bb2cd4fb2e0 100644
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -137,6 +137,18 @@ void llcoro::suspendUntilTimeout(float seconds)
suspendUntilEventOnWithTimeout(bogus, seconds, timedout);
}
+void llcoro::suspendUntilNextFrame()
+{
+ LLCoros::checkStop();
+ LLCoros::TempStatus st("waiting for next frame");
+
+ // Listen for the next event on the "mainloop" event pump.
+ // Once per frame we get mainloop.post(newFrame);
+ LLEventPumpOrPumpName mainloop_pump("mainloop");
+ // Wait for the next event (the event data is ignored).
+ suspendUntilEventOn(mainloop_pump);
+}
+
namespace
{
diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h
index 492563bb987..25a8a98e368 100644
--- a/indra/llcommon/lleventcoro.h
+++ b/indra/llcommon/lleventcoro.h
@@ -84,6 +84,11 @@ void suspend();
*/
void suspendUntilTimeout(float seconds);
+/**
+ * Yield control from a coroutine until the next mainloop's newFrame event.
+ */
+void suspendUntilNextFrame();
+
/**
* Post specified LLSD event on the specified LLEventPump, then suspend for a
* response on specified other LLEventPump. This is more than mere
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index a539e4fe282..f752e315632 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -187,13 +187,34 @@ static unsigned short get_fileattr(const std::wstring& utf16path, bool dontFollo
CloseHandle(file_handle);
return st_mode;
}
+ // Retrieve last error before calling CloseHandle()
+ DWORD last_error = GetLastError();
+ CloseHandle(file_handle);
+ set_errno_from_oserror(last_error);
+ }
+ else
+ {
+ set_errno_from_oserror(GetLastError());
}
- // Retrieve last error and set errno before calling CloseHandle()
- set_errno_from_oserror(GetLastError());
- if (file_handle != INVALID_HANDLE_VALUE)
+ // If CreateFileW approach failed (e.g., exFAT), try the simpler GetFileAttributesW()
+ // GetFileAttributesW() always follows symlinks, so we skip this fallback when dontFollowSymLink is true.
+ if (!dontFollowSymLink)
{
- CloseHandle(file_handle);
+ DWORD attributes = GetFileAttributesW(utf16path.c_str());
+ if (attributes != INVALID_FILE_ATTRIBUTES)
+ {
+ bool is_directory = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ unsigned short st_mode = is_directory ? S_IFDIR : S_IFREG;
+ st_mode |= (attributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD | S_IWRITE;
+
+ // propagate user bits to group/other fields:
+ st_mode |= (st_mode & 0700) >> 3;
+ st_mode |= (st_mode & 0700) >> 6;
+
+ return st_mode;
+ }
+ set_errno_from_oserror(GetLastError());
}
return 0;
}
diff --git a/indra/llcommon/llheteromap.cpp b/indra/llcommon/llheteromap.cpp
index 823bea7a3c1..03dd7856b60 100644
--- a/indra/llcommon/llheteromap.cpp
+++ b/indra/llcommon/llheteromap.cpp
@@ -27,6 +27,6 @@ LLHeteroMap::~LLHeteroMap()
// pair.second is the std::pair; pair.second.first is the void*;
// pair.second.second points to the deleter function
(pair.second.second)(pair.second.first);
- pair.second.first = NULL;
+ pair.second.first = nullptr;
}
}
diff --git a/indra/llcommon/llheteromap.h b/indra/llcommon/llheteromap.h
index d8e6fefb17e..211dfaae834 100644
--- a/indra/llcommon/llheteromap.h
+++ b/indra/llcommon/llheteromap.h
@@ -12,9 +12,10 @@
#if ! defined(LL_LLHETEROMAP_H)
#define LL_LLHETEROMAP_H
+#include
#include
#include // std::pair
-#include