Initialize character set encoding on program startup

libarchive uses `nl_langinfo(CODESET)` as the host's encoding to convert
path names to/from the archive's encoding.  Since commit cd408d93fd (Add
setlocale() calls around use of libarchive APIs, 2015-02-06, v3.1.3~2^2)
we've set `LC_CTYPE` using a scoped locale around libarchive calls to
avoid affecting character classification in the rest of the program.

We've since updated the rest of our code to be locale-independent.
Replace the scoped locale with a single locale established at program
startup.  This is more efficient and avoids mutating global state.

Issue: #27562
This commit is contained in:
Brad King
2026-02-11 11:55:59 -05:00
parent 6ec707312d
commit d284ce2fd6
5 changed files with 9 additions and 37 deletions
-1
View File
@@ -401,7 +401,6 @@ add_library(
cmRulePlaceholderExpander.cxx
cmRulePlaceholderExpander.h
cmLocalUnixMakefileGenerator3.cxx
cmLocale.h
cmMakefile.cxx
cmMakefile.h
cmMakefileTargetGenerator.cxx
-4
View File
@@ -24,7 +24,6 @@
#include "cm_parse_date.h"
#include "cmLocale.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -449,9 +448,6 @@ bool cmArchiveWrite::AddFile(char const* file, size_t skip, char const* prefix)
}
char const* out = file + skip;
cmLocaleRAII localeRAII;
static_cast<void>(localeRAII);
// Meta-data.
std::string dest = cmStrCat(prefix ? prefix : "", out);
if (this->Verbose) {
-26
View File
@@ -1,26 +0,0 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <clocale>
#include <string>
class cmLocaleRAII
{
public:
cmLocaleRAII()
: OldLocale(setlocale(LC_CTYPE, nullptr))
{
setlocale(LC_CTYPE, "");
}
~cmLocaleRAII() { setlocale(LC_CTYPE, this->OldLocale.c_str()); }
cmLocaleRAII(cmLocaleRAII const&) = delete;
cmLocaleRAII& operator=(cmLocaleRAII const&) = delete;
private:
std::string OldLocale;
};
+9 -3
View File
@@ -3,6 +3,7 @@
#include "cmStdIoInit.h"
#include <cerrno>
#include <clocale>
#include <cstdio>
#include <cstdlib>
#include <iostream>
@@ -106,14 +107,19 @@ public:
static Globals& Get();
};
#ifdef _WIN32
Globals::Globals()
{
#ifdef _WIN32
// On Windows, setlocale offers a ".<code-page>" syntax to select the
// user's locale with a specific character set. We always use UTF-8.
std::setlocale(LC_CTYPE, ".UTF-8");
SetConsoleCtrlHandler(CtrlHandler, TRUE);
}
#else
Globals::Globals() = default;
// On non-Windows platforms, we select the user's locale.
std::setlocale(LC_CTYPE, "");
#endif
}
Globals& Globals::Get()
{
-3
View File
@@ -58,7 +58,6 @@
# include <cm3p/archive_entry.h>
# include "cmArchiveWrite.h"
# include "cmLocale.h"
# ifndef __LA_INT64_T
# define __LA_INT64_T la_int64_t
# endif
@@ -2624,8 +2623,6 @@ bool extract_tar(std::string const& arFileName,
cmSystemTools::cmTarExtractTimestamps extractTimestamps,
bool extract)
{
cmLocaleRAII localeRAII;
static_cast<void>(localeRAII);
struct archive* a = archive_read_new();
struct archive* ext = archive_write_disk_new();
if (extract) {